Temporal overview

p_year %>% 
  inner_join(poems,by=c("p_id")) %>%
  count(collection,year) %>%
  mutate(measure="yearly count") %>%
  union_all(
    p_year %>% # 10 year rolling mean
      distinct(year) %>% 
      left_join(p_year %>% distinct(year),sql_on="RHS.year BETWEEN LHS.year-5 AND LHS.year+4") %>%
      inner_join(p_year,by=c("year.y"="year")) %>%
      inner_join(poems,by=c("p_id")) %>%
      group_by(collection=collection,year=year.x) %>%
      summarize(n=n()/n_distinct(year.y),.groups="drop") %>%
      mutate(measure="10 year rolling mean")
  ) %>%
  filter(collection!="literary",!year %in% c(0,9999)) %>%
  mutate(year=if_else(year>=1800,year,1780)) %>%
  group_by(collection,measure,year) %>%
  summarise(n=sum(n),.groups="drop") %>%
  collect() %>%
  complete(year,collection,measure,fill=list(n=0)) %>%
  mutate(collection=fct_relevel(str_to_upper(collection),"ERAB","SKVR","JR")) %>%
  group_by(collection,measure) %>%
  arrange(year) %>%
  filter(n!=0 | lag(n)!=0 | lead(n)!=0) %>%
  ungroup() %>%
  mutate(youtlier=n>4600,xoutlier=year<1800) %>%
  ggplot(aes(x=year,y=n,color=collection)) +
  geom_point(data=~.x %>% filter(measure=="yearly count",youtlier==FALSE),size=0.5) +
  geom_point(data=~.x %>% filter(youtlier==TRUE),aes(x=year),y=5000) +
  geom_text_repel(data=~.x %>% filter(youtlier==TRUE),aes(x=year,label=scales::number(n)),y=5000, show.legend=FALSE) +
  geom_point(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=year,y=n)) +
  geom_text_repel(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=year,y=n,label=scales::number(n)), show.legend=FALSE) +  
  geom_line(data=~.x %>% filter(xoutlier==FALSE,measure=="10 year rolling mean")) +
  theme_hsci_discrete(base_family="Arial") + 
  theme(
    legend.justification=c(0,1), 
    legend.position=c(0.02, 0.98), 
    legend.background = element_blank(), 
    legend.key=element_blank()
  ) + 
  labs(color=NULL) +
  coord_cartesian(ylim=c(0,4600),xlim=c(1800,1970),clip="off") +
  scale_y_continuous(breaks=seq(0,20000,by=1000),labels=scales::number) +
#  ylab("Poems") +
  ylab("Runojen määrä") +
  scale_x_continuous(breaks=seq(1000,2000,by=10)) +
#  xlab("Year") +
  xlab("Vuosi") +
  ggtitle("")

#  ggtitle("Runojen määrä vuosittain ja kokoelmittain")
#  ggtitle("Number of poems by year and collection")
top_top_themes <- poem_theme %>% 
  inner_join(poems) %>%
  inner_join(themes_to_top_level_themes) %>%
  count(collection, ancestor_t_id) %>%
  group_by(collection) %>%
  slice_max(n,n=9) %>%
  ungroup() %>% 
  mutate(top_theme=TRUE) %>%
  select(ancestor_t_id,top_theme) %>%
  compute_a(temporary=TRUE, overwrite=TRUE)
d <- p_year %>% 
  inner_join(poems,by=c("p_id")) %>%
  inner_join(poem_theme %>%
    inner_join(themes_to_top_level_themes %>% 
                 inner_join(themes %>%
                              filter(!str_detect(theme_id,"^erab_orig")) %>%
                        select(ancestor_t_id=t_id,ancestor_theme_name=name)))) %>%
  left_join(top_top_themes) %>%
  mutate(
    ancestor_theme_name=if_else(!is.na(top_theme),ancestor_theme_name,"Muut"),
    ancestor_t_id=if_else(!is.na(top_theme),ancestor_t_id,-1),
    ) %>%
  replace_na(list(ancestor_theme_name="Tuntematon", ancestor_t_id=-2)) %>%
  distinct(ancestor_t_id,ancestor_theme_name, collection, year, p_id) %>%
  count(ancestor_t_id,ancestor_theme_name, collection, year) %>%
  mutate(measure="yearly count") %>%
  union_all(
    p_year %>% # 10 year rolling mean
      distinct(year) %>% 
      left_join(p_year %>% distinct(year),sql_on="RHS.year BETWEEN LHS.year-5 AND LHS.year+4") %>%
      inner_join(p_year,by=c("year.y"="year")) %>%
      inner_join(poems,by=c("p_id")) %>%
      inner_join(poem_theme %>%
        inner_join(themes_to_top_level_themes %>% 
                     inner_join(themes %>% 
                                  filter(!str_detect(theme_id,"^erab_orig")) %>% 
                                  select(ancestor_t_id=t_id,ancestor_theme_name=name)))) %>%
      left_join(top_top_themes) %>%
      mutate(
        ancestor_theme_name=if_else(!is.na(top_theme),ancestor_theme_name,"Muut"),
        ancestor_t_id=if_else(!is.na(top_theme),ancestor_t_id,-1),
        ) %>%
      replace_na(list(ancestor_theme_name="Tuntematon", ancestor_t_id=-2)) %>%
      distinct(ancestor_t_id,ancestor_theme_name, collection, year.x, year.y, p_id) %>%
      group_by(ancestor_t_id,ancestor_theme_name, collection, year=year.x) %>%
      summarize(n=n()/n_distinct(year.y),.groups="drop") %>%
      mutate(measure="10 year rolling mean")
  ) %>%
  filter(collection!="literary",!year %in% c(0L,9999L)) %>%
  mutate(year=if_else(year>=1800L,year,1780L)) %>%
  group_by(ancestor_theme_name, collection, measure, year) %>%
  summarise(n=sum(n),.groups="drop") %>%
  collect()
Warning: Missing values are always removed in SQL aggregation functions.
Use `na.rm = TRUE` to silence this warning
d %>%
  mutate(collection=fct_relevel(str_to_upper(collection),"SKVR","ERAB","JR")) %>%
  filter(collection=="SKVR") %>%
  complete(ancestor_theme_name, year,collection,measure,fill=list(n=0)) %>%
  group_by(ancestor_theme_name, collection,measure) %>%
  arrange(year) %>%
  filter(n!=0 | lag(n)!=0 | lead(n)!=0) %>%
  ungroup() %>%
  mutate(youtlier=n>1300,xoutlier=year<1800) %>%
  ggplot(aes(x=year,y=n,color=ancestor_theme_name)) +
#  facet_wrap(~collection) +
  geom_point(data=~.x %>% filter(measure=="yearly count",youtlier==FALSE,xoutlier==FALSE),size=0.5) +
  geom_point(data=~.x %>% filter(youtlier==TRUE),aes(x=year),y=1400) +
  geom_text_repel(data=~.x %>% filter(youtlier==TRUE),aes(x=year,label=scales::number(n)),y=1400, show.legend=FALSE) +
  geom_point(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=1785,y=n)) +
  geom_text_repel(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=1785,y=n,label=scales::number(n)), show.legend=FALSE) +  
  geom_line(data=~.x %>% filter(xoutlier==FALSE,measure=="10 year rolling mean")) +
  theme_hsci_discrete(base_family="Arial") + 
  theme(
    legend.justification=c(0,1), 
    legend.position=c(0.02, 0.98), 
    legend.background = element_blank(), 
    legend.key=element_blank()
  ) + 
  labs(color=NULL) +
  coord_cartesian(ylim=c(0,1300),xlim=c(1800,1940),clip="off") +
  scale_y_continuous(breaks=seq(0,20000,by=500),labels=scales::number) +
#  ylab("Poems") +
  ylab("Runojen määrä") +
  scale_x_continuous(breaks=seq(1000,2000,by=10)) +
#  xlab("Year") +
  xlab("Vuosi") +
  ggtitle("")
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `collection = fct_relevel(str_to_upper(collection),
  "SKVR", "ERAB", "JR")`.
Caused by warning:
! 1 unknown level in `f`: JR

#  ggtitle("Runojen määrä vuosittain ja kokoelmittain")
#  ggtitle("Number of poems by year and collection")
d %>%
  mutate(collection=fct_relevel(str_to_upper(collection),"SKVR","ERAB")) %>%
  filter(collection=="ERAB") %>%
  complete(ancestor_theme_name, year,collection,measure,fill=list(n=0)) %>%
  group_by(ancestor_theme_name, collection,measure) %>%
  arrange(year) %>%
  filter(n!=0 | lag(n)!=0 | lead(n)!=0) %>%
  ungroup() %>%
  mutate(youtlier=n>820,xoutlier=year<1800) %>%
  mutate(ancestor_theme_name=case_match(ancestor_theme_name,
    "Laulud noorrahva elust" ~ "Laulut nuorison elämästä (Laulud noorrahva elust)",
    "Muut" ~ "Muut (sisältää 17 luokkaa)",
    "Laulud meelelahutamiseks" ~ "Viihdytyslaulut (Laulud meelelahutamiseks)",
    "Lüroeepilised laulud" ~ "Lyroeeppiset laulut (Lüroeepilised laulud)",
    "Laulud laulust" ~ "Laulut laulusta (Laulud laulust)",
    "Töölaulud" ~ "Työlaulut (Töölaulud)",
    "Looduslaulud" ~ "Laulut luonnosta (Looduslaulud)",
    "Laulud ühiskondlikest vahekordadest" ~ "Laulut yhteiskunnallisista suhteista\n(Laulud ühiskondlikest vahekordadest)",
    "Murelaulud" ~ "Huolilaulut (Murelaulud)",
    "Laulud abielust" ~ "Laulut avioelämästä (Laulud abielust)",
    "Kalendrilaulud" ~ "Kalendaarilaulut (Kalendrilaulud)"
  )) %>%
  mutate(ancestor_theme_name=fct_reorder(ancestor_theme_name,n,.fun=sum,.desc=TRUE)) %>%
  mutate(ancestor_theme_name=fct_relevel(ancestor_theme_name, "Muut (sisältää 17 luokkaa)", after=Inf)) %>%
  ggplot(aes(x=year,y=n,color=ancestor_theme_name)) +
#  facet_wrap(~collection) +
  geom_point(data=~.x %>% filter(measure=="yearly count",youtlier==FALSE,xoutlier==FALSE),size=0.5) +
  geom_point(data=~.x %>% filter(youtlier==TRUE),aes(x=year),y=900) +
  geom_text_repel(data=~.x %>% filter(youtlier==TRUE),aes(x=year,label=scales::number(n)),y=900, show.legend=FALSE) +
  geom_point(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=1785,y=n)) +
  geom_text_repel(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=1785,y=n,label=scales::number(n)), show.legend=FALSE) +  
  geom_line(data=~.x %>% filter(xoutlier==FALSE,measure=="10 year rolling mean")) +
  theme_hsci_discrete(base_family="Arial") + 
  theme(
    legend.box.just = "top",
    legend.justification=c(0,1), 
    legend.position=c(0.02, 0.98), 
    legend.background = element_blank(), 
    legend.key=element_blank()
  ) + 
  labs(color=NULL) +
  coord_cartesian(ylim=c(0,820),xlim=c(1820,1950),clip="off") +
  scale_y_continuous(breaks=seq(0,20000,by=200),labels=scales::number) +
#  ylab("Poems") +
  ylab("Runojen määrä") +
#  guides(color=guide_legend(nrow=2)) +
  scale_x_continuous(breaks=seq(1000,2000,by=10)) +
#  xlab("Year") +
  xlab("Vuosi") +
  ggtitle("")

#  ggtitle("Runojen määrä vuosittain ja kokoelmittain")
#  ggtitle("Number of poems by year and collection")
d %>%
  mutate(collection=fct_relevel(str_to_upper(collection),"SKVR","ERAB","JR")) %>%
  filter(collection=="JR") %>%
  complete(ancestor_theme_name, year,collection,measure,fill=list(n=0)) %>%
  group_by(ancestor_theme_name, collection,measure) %>%
  arrange(year) %>%
  filter(n!=0 | lag(n)!=0 | lead(n)!=0) %>%
  ungroup() %>%
  mutate(youtlier=n>6500,xoutlier=year<1800) %>%
  ggplot(aes(x=year,y=n,color=ancestor_theme_name)) +
#  facet_wrap(~collection) +
  geom_point(data=~.x %>% filter(measure=="yearly count",youtlier==FALSE),size=0.5) +
  geom_point(data=~.x %>% filter(youtlier==TRUE),aes(x=year),y=7200) +
  geom_text_repel(data=~.x %>% filter(youtlier==TRUE),aes(x=year,label=scales::number(n)),y=7200, show.legend=FALSE) +
  geom_point(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=year,y=n)) +
  geom_text_repel(data=~.x %>% filter(xoutlier==TRUE,measure=="yearly count"),aes(x=year,y=n,label=scales::number(n)), show.legend=FALSE) +  
  geom_line(data=~.x %>% filter(xoutlier==FALSE,measure=="10 year rolling mean")) +
  theme_hsci_discrete(base_family="Arial") + 
  theme(
    legend.justification=c(0,1), 
    legend.position=c(0.02, 0.98), 
    legend.background = element_blank(), 
    legend.key=element_blank()
  ) + 
  labs(color=NULL) +
  coord_cartesian(ylim=c(0,6500),xlim=c(1800,1960),clip="off") +
  scale_y_continuous(breaks=seq(0,20000,by=1000),labels=scales::number) +
#  ylab("Poems") +
  ylab("Runojen määrä") +
  scale_x_continuous(breaks=seq(1000,2000,by=10)) +
#  xlab("Year") +
  xlab("Vuosi") +
  ggtitle("")

#  ggtitle("Runojen määrä vuosittain ja kokoelmittain")
#  ggtitle("Number of poems by year and collection")
p_year %>% 
  filter(year %in% c(0,9999)) %>% 
  left_join(poems) %>% 
  count(collection,year) %>%
  ungroup() %>%
  gt() %>%
  tab_header(title=\Abnormal years\) %>%
  fmt_integer(n)

Overview of collectors

poems %>% 
  distinct(collection) %>%
  pull() %>%
  map(~p_col %>% 
    inner_join(poems %>% filter(collection==.x),by=c(\p_id\)) %>%
    count(col_id) %>%
    left_join(collectors,by=c(\col_id\)) %>%
    select(col_id,name,n) %>%
    collect() %>%
    mutate(col_id=fct_reorder(str_c(col_id,\|\,name),n)) %>%
    mutate(col_id=fct_lump_n(col_id,n=100,w=n)) %>%
    mutate(col_id=fct_relevel(col_id,\Other\)) %>%
    group_by(col_id) %>%
    tally(wt=n) %>% {
      ggplot(.,aes(x=col_id,y=n)) +
      geom_col() +
      geom_text(aes(label=p(n)),hjust='left',nudge_y = 100) +
      theme_hsci_discrete(base_family=\Arial\) +
      coord_flip() +
      labs(title=str_c(\Collectors in \,.x))
    }
  )
[[1]]


[[2]]


[[3]]


[[4]]

p_col %>% 
  anti_join(collectors) %>%
  count(col_id) %>%
  gt() %>%
  tab_header(title=\Collectors without a name\) %>%
  fmt_integer(n)
p_col %>%
  inner_join(collectors) %>%
  inner_join(poems) %>%
  filter(collection!="literary") %>%
  mutate(collection=str_to_upper(collection)) %>%
  count(collection,col_id,name) %>%
  group_by(collection) %>%
  slice_max(order_by=n,n=10) %>%
  ungroup() %>%
  select(-col_id) %>%
  gt(groupname_col = "collection", rowname_col = "name") %>%
  row_group_order(c("ERAB","SKVR","JR")) %>%
  fmt_integer(n,sep_mark=" ")
n
ERAB
Rosenstrauch, Karl Voldemar 3 825
Viljak, Karl 3 225
Ostrov, Mihkel 2 300
Vilberg (Vilbaste), Gustav 2 218
Viidalepp (Viidebaum), Richard 2 134
Kallas, Oskar Philipp 1 723
Seen, Gustav 1 473
Penna, Peeter 1 312
Tampere, Herbert 1 188
koguja teadmata 1 175
SKVR
Krohn, Kaarle 4 110
Paulaharju, Samuli ja Jenni 3 157
Alava, Vihtori 3 089
Europaeus, D. E. D. 2 899
Neovius, A. D. 2 535
Porkka, Volmari 2 424
Lönnrot, Elias 2 402
Perä-Pohjolan ja Lapin Kotiseutuyhdistys 2 172
Salminen, Väinö 1 761
Vihervaara, Eemeli 1 702
JR
Hämeenlinnan alakansakouluseminaari 6 782
Perä-Pohjolan ja Lapin Kotiseutuyhdistys 3 463
Kärki, Frans 3 157
Railonsala, Artturi 2 452
Paulaharju, Samuli ja Jenni 2 168
Sääski, Sylvi 1 666
Saarijärven yhteiskoulu 1 652
Pennanen, Olavi 1 448
Paavolainen, Oma Martti 1 265
Lönnrot, Elias 1 239
p_col %>%
  inner_join(collectors) %>%
  inner_join(poems) %>%
  filter(collection!="literary") %>%
  mutate(collection=str_to_upper(collection)) %>%
  count(collection,col_id,name) %>%
  group_by(collection) %>%
  slice_max(order_by=n,n=10) %>%
  ungroup() %>%
  inner_join(p_col) %>%
  inner_join(poem_theme) %>%
  inner_join(themes_to_top_level_themes) %>%
  count(collection, col_id, t_id=ancestor_t_id) %>%
  inner_join(themes %>% rename(theme_name=name)) %>%
  inner_join(collectors) %>%
  filter(collection=="SKVR") %>%
  collect() %>% 
#  group_by(collection) %>%
#  mutate(theme_name=fct_lump_n(theme_name, n, n=5, other_level="Muut")) %>%
#  ungroup() %>%
  group_by(col_id) %>%
  mutate(tn=sum(n)) %>%
  ungroup() %>%
  mutate(name=fct_reorder(name,tn)) %>%
  ggplot(aes(x=name,fill=theme_name,y=n)) +
#  facet_wrap(~collection,scales="free",ncol=1) +
  geom_col() +
  theme_hsci_discrete() +
  coord_flip() +
  scale_y_continuous(labels=scales::number) +
  labs(fill="Päätyyppi") +
  xlab("Kerääjä") +
  ylab("Tyyppimerkintöjä")

Geographical overview

d <- p_loc %>% 
  count(loc_id) %>% 
  inner_join(locations) %>%
  select(name,n) %>%
  collect()

poems_without_location <- poems %>% 
  anti_join(p_loc) %>% 
  count() %>% 
  pull()

unprojected_locations <- d %>%
  anti_join(polygons) %>%
  add_row(name=NA,n=poems_without_location)
polygons %>%
  left_join(d) %>%
  tm_shape() +
  tm_polygons(col='n', id='name', style='fisher', palette='plasma') +
  tm_layout(title=str_c(\Geographical overview. Missing \,unprojected_locations %>% tally(wt=n) %>% pull() %>% p,\ poems.\))

tm_tiles #FFFFFF00 blank Esri.WorldGrayCanvas

OpenStreetMap

Esri.WorldTopoMap base n name tm_fill #666666 solid #0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#7E03A8

#7E03A8

#BFBFBF

#0D0887

#7E03A8

#7E03A8

#F89441

#F89441

#CC4678

#CC4678

#0D0887

#0D0887

#0D0887

#BFBFBF

#7E03A8

#0D0887

#BFBFBF

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#F89441

#0D0887

#7E03A8

#7E03A8

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#CC4678

#7E03A8

#0D0887

#0D0887

#7E03A8

#0D0887

#F89441

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#CC4678

#0D0887

#0D0887

#0D0887

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#BFBFBF

#7E03A8

#F89441

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#7E03A8

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#7E03A8

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#BFBFBF

#7E03A8

#0D0887

#0D0887

#7E03A8

#7E03A8

#0D0887

#7E03A8

#0D0887

#7E03A8

#BFBFBF

#7E03A8

#0D0887

#0D0887

#7E03A8

#7E03A8

#7E03A8

#CC4678

#7E03A8

#CC4678

#7E03A8

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#7E03A8

#BFBFBF

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#CC4678

#7E03A8

#0D0887

#7E03A8

#0D0887

#F89441

#7E03A8

#F89441

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#7E03A8

#BFBFBF

#CC4678

#CC4678

#7E03A8

#0D0887

#BFBFBF

#CC4678

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#CC4678

#BFBFBF

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#7E03A8

#CC4678

#0D0887

#BFBFBF

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#F89441

#BFBFBF

#7E03A8

#7E03A8

#7E03A8

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#7E03A8

#0D0887

#7E03A8

#7E03A8

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#CC4678

#BFBFBF

#0D0887

#0D0887

#F0F921

#7E03A8

#0D0887

#0D0887

#0D0887

#7E03A8

#BFBFBF

#BFBFBF

#0D0887

#7E03A8

#0D0887

#BFBFBF

#CC4678

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#BFBFBF

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#7E03A8

#F0F921

#0D0887

#0D0887

#CC4678

#BFBFBF

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#7E03A8

#BFBFBF

#0D0887

#7E03A8

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#BFBFBF

#BFBFBF

#7E03A8

#0D0887

#BFBFBF

#0D0887

#7E03A8

#0D0887

#7E03A8

#0D0887

#BFBFBF

#7E03A8

#0D0887

#7E03A8

#7E03A8

#BFBFBF

#0D0887

#0D0887

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#F89441

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#CC4678

#BFBFBF

#7E03A8

#7E03A8

#BFBFBF

#0D0887

#CC4678

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#CC4678

#0D0887

#7E03A8

#BFBFBF

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#BFBFBF

#7E03A8

#0D0887

#0D0887

#0D0887

#CC4678

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#7E03A8

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#CC4678

#0D0887

#0D0887

#0D0887

#CC4678

#7E03A8

#7E03A8

#0D0887

#BFBFBF

#CC4678

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#7E03A8

#BFBFBF

#7E03A8

#BFBFBF

#7E03A8

#0D0887

#7E03A8

#0D0887

#0D0887

#CC4678

#0D0887

#7E03A8

#0D0887

#CC4678

#BFBFBF

#CC4678

#CC4678

#BFBFBF

#BFBFBF

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#7E03A8

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#BFBFBF

#7E03A8

#F89441

#0D0887

#0D0887

#BFBFBF

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#0D0887

#7E03A8

#0D0887

#7E03A8

#0D0887

#7E03A8

#BFBFBF

#0D0887

#7E03A8

#0D0887

#7E03A8

#7E03A8

#7E03A8

#7E03A8

#CC4678

#CC4678

#0D0887

#7E03A8

#0D0887

#0D0887

#BFBFBF

#F89441

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#7E03A8

#BFBFBF

#0D0887

#0D0887

#7E03A8

#7E03A8

#0D0887

#0D0887

#7E03A8

#0D0887

#CC4678

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#BFBFBF

#CC4678

#F89441

#7E03A8

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#F89441

#7E03A8

#0D0887

#CC4678

#0D0887

#CC4678

#CC4678

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#BFBFBF

#0D0887

#0D0887

#7E03A8

#0D0887

#7E03A8

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#CC4678

#7E03A8

#0D0887

#0D0887

#BFBFBF

#0D0887

#BFBFBF

#CC4678

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#BFBFBF

#7E03A8

#BFBFBF

#0D0887

#0D0887

#F89441

#7E03A8

#0D0887

#7E03A8

#7E03A8

#BFBFBF

#7E03A8

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#F0F921

#BFBFBF

#F0F921

#7E03A8

#0D0887

#0D0887

#CC4678

#CC4678

#CC4678

#0D0887

#7E03A8

#0D0887

#7E03A8

#0D0887

#CC4678

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#7E03A8

#7E03A8

#0D0887

#0D0887

#CC4678

#7E03A8

#CC4678

#CC4678

#0D0887

#7E03A8

#7E03A8

#CC4678

#F89441

#BFBFBF

#BFBFBF

#0D0887

#CC4678

#CC4678

#0D0887

#7E03A8

#0D0887

#0D0887

#7E03A8

#0D0887

#BFBFBF

#0D0887

#7E03A8

#0D0887

#7E03A8

#CC4678

#0D0887

#0D0887

#CC4678

#CC4678

#0D0887

#0D0887

#0D0887

#CC4678

#0D0887

#F89441

#BFBFBF

#0D0887

#0D0887

#7E03A8

#0D0887

#BFBFBF

#0D0887

#BFBFBF

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#CC4678

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#CC4678

#7E03A8

#7E03A8

#0D0887

#BFBFBF

#0D0887

#7E03A8

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#7E03A8

#0D0887

#7E03A8

#BFBFBF

#0D0887

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#CC4678

#0D0887

#7E03A8

#0D0887

#0D0887

#7E03A8

#F89441

#7E03A8

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#BFBFBF

#CC4678

#BFBFBF

#0D0887

#0D0887

#0D0887

#F89441

#F0F921

#CC4678

#BFBFBF

#0D0887

#7E03A8

#BFBFBF

#0D0887

#0D0887

#0D0887

#F0F921

#0D0887

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#7E03A8

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#0D0887

#BFBFBF

#0D0887

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#F89441

#0D0887

#0D0887

#CC4678

#BFBFBF

#BFBFBF

#BFBFBF

#7E03A8

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#7E03A8

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#CC4678

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#F89441

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#7E03A8

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#7E03A8

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#BFBFBF

#0D0887

#0D0887

#7E03A8

#0D0887

#BFBFBF

#0D0887

#CC4678

#7E03A8

#7E03A8

#F0F921

#F89441

#7E03A8

#0D0887

#BFBFBF

#F89441 1 to 312

312 to 847

847 to 1,732

1,732 to 3,075

3,075 to 3,985

Missing #0D0887

#7E03A8

#CC4678

#F89441

#F0F921

#BFBFBF #666666 n n name to Less

than or

more metric png Geographical overview. Missing 37,345 poems. #FFFFFF YlOrBr RdYlGn Set3 black #000000 plain #000000 #FFFFFF right vertical left

bottom #000000 plain #000000 plain to Less

than or

more left

top #000000 plain #000000 plain #CCCCCC #000000 plain left bottom right

bottom left

bottom Esri.WorldGrayCanvas

OpenStreetMap

Esri.WorldTopoMap topright left

top grey85

grey40

grey60

black

black

black

grey75

grey95 Missing dummy

. km none km km

Poem locations not mapped

unprojected_locations %>%
  arrange(desc(n)) %>%
  gt() %>%
  tab_header(\Poem locations not mapped\) %>%
  fmt_integer(n)

Geographical overview by collection

d <- p_loc %>% 
  left_join(poems) %>%
  count(collection,loc_id) %>% 
  ungroup() %>%
  inner_join(locations) %>%
  select(collection,name,n) %>%
  collect()

poems_without_location <- poems %>% 
  anti_join(p_loc) %>% 
  count(collection) %>% 
  collect() %>%
  mutate(name=NA_character_)

unprojected_locations <- d %>%
  anti_join(polygons) %>%
  union_all(poems_without_location)
poems %>% 
  distinct(collection) %>%
  pull() %>%
  map(~
    tm_shape(
      polygons %>%
        left_join(
          p_loc %>% 
            inner_join(poems %>% filter(collection==.x),by=c(\p_id\)) %>%
            count(loc_id) %>% 
            inner_join(locations) %>%
            select(name,n) %>%
            collect()
        )
    ) +
    tm_polygons(col='n', id='name', style='fisher', palette='plasma') +
    tm_layout(title=str_c(\Geography of \,.x,\. Missing \,unprojected_locations %>% filter(collection==.x) %>% tally(wt=n) %>% pull() %>% p,\ poems.\))
  )
[[1]]


[[2]]


[[3]]


[[4]]

Poem locations not mapped by collection

poems %>% 
  distinct(collection) %>%
  pull() %>%
  map(~
    unprojected_locations %>%
      filter(collection==.x) %>%
      arrange(desc(n)) %>%
      select(-collection) %>%
      gt() %>%
      tab_header(str_c(\Poem locations not mapped in \,.x)) %>%
      fmt_integer(n)
  )

Informants

raw_meta %>% 
  filter(field=="INF") %>%
  mutate(value_c=str_replace_all(value,"^\\s*[A-Za-zÅÄÖåäö][a-zåäö][a-zåäö]+\\.","")) %>% 
  mutate(name=str_replace_all(value_c,"\\s*\"*([A-Za-zÅÄÖåäö]?[a-zåäö]?[a-zåäö]?\\.?[^;.,]+)(.|\\n)*","\\1")) %>% 
  group_by(name) %>% 
  summarise(origs=str_flatten(sql("distinct value"),collapse="|"),n=n(),.groups="drop") %>% 
  collect()

Poem types

poems %>% 
  filter(collection!="literary") %>%
  left_join(poem_theme %>% filter(is_minor==0) %>% inner_join(themes %>% mutate(theme_type=if_else(str_detect(theme_id,"^erab_orig"),"Non-unified","Unified")))) %>% 
  group_by(collection,p_id) %>%
  summarise(theme_type=case_when(
    any(theme_type=="Unified") ~ "Systematisoituja", 
    any(theme_type=="Non-unified") ~ "Vain ei-systematisoituja", 
    T ~ "Ei annotointeja"), .groups="drop") %>%
  count(collection,theme_type) %>%
  collect() %>%
  mutate(collection=fct_rev(fct_relevel(str_to_upper(collection),"ERAB","SKVR","JR")),theme_type=fct_rev(fct_relevel(theme_type,"Systematisoituja","Vain ei-systematisoituja","Ei annotointeja"))) %>%
  ggplot(aes(x=collection,y=n,fill=theme_type)) + 
  geom_col() + 
  theme_hsci_discrete() + 
  xlab("Kokoelma") +
  ylab("Runoja") +
  labs(fill="Runotyyppiannotaatiot") +
  theme(legend.position="bottom") +
  guides(fill = guide_legend(reverse = TRUE)) +
  scale_y_continuous(labels=scales::number) +
  coord_flip()

Spatiotemporal overview

d <- poems %>%
  left_join(p_year %>% mutate(year=if_else(year %in% c(0L,9999L),NA,year))) %>% 
  collect() %>%
  mutate(year_ntile=ntile(year,11)) %>%
  group_by(year_ntile) %>%
  mutate(years=str_c(min(year),\-\,max(year))) %>%
  ungroup() %>%
  left_join(p_loc %>% collect()) %>% 
  count(years,loc_id) %>% 
  ungroup() %>%
  left_join(locations %>% select(loc_id,name) %>% collect())
polygons %>% 
  left_join(d %>% complete(name,years)) %>%
  tm_shape() +
  tm_polygons(col='n', id='name', style='fisher', palette='plasma') +
  tm_layout(main.title=\Geographical overviews by time\,legend.outside.size=0.1) +
  tm_facets(by=\years\,ncol=4)

Poem length statistics

By collection

poem_stats %>%
  filter(nverses<=75) %>%
  inner_join(poems) %>%
  count(collection,nverses) %>%
  ungroup() %>%
  ggplot(aes(x=nverses,y=n)) +
  geom_col(width=1) +
  facet_wrap(~collection,scales="free_y") +
  theme_hsci_discrete(base_family="Arial") +
  scale_y_continuous(labels=scales::comma_format()) +
  xlab("Number of characters") +
  ylab("Verses") +
  labs(title="Number of verse lines")

poem_stats %>%
  inner_join(poems) %>%
  count(collection,nverses) %>%
  ungroup() %>%
  group_by(collection) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(nverses<=75) %>%
  ggplot(aes(x=nverses,y=collection,fill=collection,height=prop)) +
  geom_density_ridges(stat='identity') +
  theme_hsci_discrete(base_family="Arial") +
#  scale_y_continuous(labels=scales::percent_format()) +
  xlab("Number of verse lines") +
  ylab("Poems") +
  labs(title="Number of verse lines")

Poems with more than 75 verse lines

poem_stats %>%
  inner_join(poems) %>%
  count(collection,nverses) %>%
  mutate(nl=if_else(nverses>75,n,0L)) %>%
  group_by(collection) %>%
  summarise(lines=sum(nl),proportion=sum(nl)/sum(n),.groups="drop") %>%
  arrange(desc(lines)) %>%
  gt() %>%
  tab_header(title="Poems with more than 75 verses") %>%
  fmt_integer(lines) %>%
  fmt_percent(proportion)
Poems with more than 75 verses
collection lines proportion
skvr 2,370 2.66%
erab 1,899 1.90%
jr 1,288 1.51%
literary 114 15.24%

By county

poem_stats %>% 
  left_join(p_loc) %>% 
  left_join(locations) %>% 
  left_join(locations,by=c("par_id"="loc_id")) %>% 
  mutate(name=if_else(type.x=="county",name.x,name.y)) %>%
  count(name,nverses) %>%
  ungroup() %>%
  group_by(name) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(nverses<=40,name!="Ahvenanmaa") %>%
  collect() %>%
  mutate(name=fct_reorder(name,prop,.fun=max)) %>%
  ggplot(aes(x=nverses,y=name,height=prop)) +
  geom_density_ridges(stat='identity') +
  theme_hsci_continuous(base_family="Arial") +
#  scale_y_continuous(labels=scales::percent_format()) +
  xlab("Number of verse lines") +
  ylab("Poems") +
  guides(fill="none") +
  labs(title="Number of verse lines by county")

Poem verse statistics

By collection

Line types

d <- verses %>% 
  left_join(verse_poem) %>% 
  left_join(poems) %>% 
  count(collection,type) %>% 
  ungroup() %>%
  arrange(collection,desc(n)) %>%
  collect()
d %>% 
  group_by(collection) %>%
  mutate(proportion=n/sum(n)) %>%
  gt() %>%
  fmt_integer(n) %>%
  fmt_percent(proportion)
type n proportion
skvr
V 1,340,987 94.63%
L 44,303 3.13%
CPT 27,869 1.97%
K 3,931 0.28%
erab
V 1,861,583 93.39%
PAG 53,040 2.66%
CPT 19,844 1.00%
L 18,465 0.93%
TYH 18,357 0.92%
REF 17,869 0.90%
LRY 3,868 0.19%
RRE 307 0.02%
MRK 52 0.00%
U 38 0.00%
LLI 2 0.00%
TYP 1 0.00%
jr
V 812,343 90.94%
L 49,411 5.53%
CPT 28,030 3.14%
K 3,502 0.39%
literary
V 82,460 97.54%
L 1,220 1.44%
CPT 777 0.92%
K 87 0.10%

Verse line lengths

d_nr_characters <- verses_cl %>%
  mutate(nr_characters=str_length(text)) %>%
  left_join(verse_poem) %>% 
  left_join(poems) %>% 
  count(collection,nr_characters) %>% 
  ungroup() %>%
  arrange(collection,desc(n)) %>%
  collect()

d_nr_words <- word_occ %>%
  group_by(v_id) %>%
  summarise(nr_words=max(pos),.groups="drop") %>%
  left_join(verse_poem) %>%
  left_join(poems) %>% 
  count(collection,nr_words) %>% 
  ungroup() %>%
  arrange(collection,desc(n)) %>%
  collect()

Verse line lengths in characters

d_nr_characters %>% 
  filter(nr_characters<=60) %>%
  ggplot(aes(x=nr_characters,y=n)) +
  geom_col(width=1) +
  facet_wrap(~collection,scales=\free_y\) +
  theme_hsci_discrete(base_family=\Arial\) +
  scale_y_continuous(labels=scales::comma_format()) +
  xlab(\Number of characters\) +
  ylab(\Verses\) +
  labs(title=\Number of characters in verse lines\)

d_nr_characters %>% 
  group_by(collection) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(nr_characters<=60) %>%
  ggplot(aes(x=nr_characters,y=collection,fill=collection,height=prop)) +
  geom_density_ridges(stat='identity') +
  theme_hsci_discrete(base_family=\Arial\) +
#  scale_y_continuous(labels=scales::percent_format()) +
  xlab(\Number of characters\) +
  ylab(\Verses\) +
  labs(title=\Number of characters in verse lines\)

Verse lines with more than 60 characters

d_nr_characters %>% 
  mutate(nl=if_else(nr_characters>60,n,0L)) %>%
  group_by(collection) %>%
  summarise(lines=sum(nl),proportion=sum(nl)/sum(n),.groups=\drop\) %>%
  arrange(desc(lines)) %>%
  gt() %>%
  tab_header(title=\Verse lines with more than 60 characters\) %>%
  fmt_integer(lines) %>%
  fmt_percent(proportion)

Verse line lengths in words

d_nr_words %>% 
  filter(nr_words<=10) %>%
  ggplot(aes(x=nr_words,y=n)) +
  geom_col(width=1) +
  facet_wrap(~collection,scales=\free_y\) +
  scale_x_continuous(breaks=seq(0,10,by=2)) +
  scale_y_continuous(labels=scales::comma_format()) +
  theme_hsci_discrete(base_family=\Arial\) +
  xlab(\Number of words\) +
  ylab(\Verses\) +
  labs(title=\Number of words in verse lines\)

d_nr_words %>% 
  filter(nr_words<=10) %>%
  uncount(n) %>%
  ggplot(aes(x=nr_words,y=collection,fill=collection)) +
  stat_binline(binwidth=1) +
  theme_hsci_discrete(base_family=\Arial\) +
  scale_x_continuous(breaks=seq(0,10,by=2)) +
  xlab(\Number of words\) +
  ylab(\Verses\) +
#  scale_y_continuous(labels=scales::percent_format()) +
  labs(title=\Number of words in verse lines\)

Verse lines with more than 10 words

d_nr_words %>% 
  mutate(nl=if_else(nr_words>10,n,0L)) %>%
  group_by(collection) %>%
  summarise(lines=sum(nl),proportion=sum(nl)/sum(n),.groups=\drop\) %>%
  arrange(desc(lines)) %>%
  gt() %>%
  tab_header(title=\Verse lines with more than 10 words\) %>%
  fmt_integer(lines) %>%
  fmt_percent(proportion)
verse_nr_words <- word_occ %>% 
  group_by(v_id) %>%
  summarise(nr_words=max(pos)) %>%
  compute_a(unique_indexes=list(c(\v_id\,\nr_words\)))

word_nr_characters <- words %>%
  mutate(nr_characters=str_length(text)) %>%
  select(w_id,nr_characters) %>%
  compute_a(unique_indexes=list(c(\w_id\,\nr_characters\)))

d <- word_occ %>%
  left_join(word_nr_characters) %>%
  left_join(verse_nr_words) %>%
  left_join(verse_poem %>% select(-pos),by=c(\v_id\)) %>% 
  left_join(poems) %>% 
  count(collection,nr_words,pos,nr_characters) %>%
  collect()

By county

Verse line lengths

d_nr_characters <- verses_cl %>%
  mutate(nr_characters=str_length(text)) %>%
  left_join(verse_poem) %>% 
  left_join(p_loc) %>% 
  left_join(locations) %>% 
  left_join(locations,by=c("par_id"="loc_id")) %>% 
  mutate(name=if_else(type.x=="county",name.x,name.y)) %>%
  count(name,nr_characters) %>% 
  ungroup() %>%
  arrange(name,desc(n)) %>%
  collect()

d_nr_words <- word_occ %>%
  group_by(v_id) %>%
  summarise(nr_words=max(pos),.groups="drop") %>%
  left_join(verse_poem) %>%
  left_join(p_loc) %>% 
  left_join(locations) %>% 
  left_join(locations,by=c("par_id"="loc_id")) %>% 
  mutate(name=if_else(type.x=="county",name.x,name.y)) %>%
  count(name,nr_words) %>% 
  ungroup() %>%
  arrange(name,desc(n)) %>%
  collect()

Verse line lengths in characters

d_nr_characters %>% 
  group_by(name) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(nr_characters<=40,name!="Ahvenanmaa") %>%
  mutate(name=fct_reorder(name,prop,.fun=max)) %>%
  ggplot(aes(x=nr_characters,y=name,height=prop)) +
  geom_density_ridges(stat='identity') +
  theme_hsci_discrete(base_family="Arial") +
#  scale_y_continuous(labels=scales::percent_format()) +
  xlab("Number of characters") +
  ylab("Verses") +
  labs(title="Number of characters in verse lines")

Verse line lengths in words

d_nr_words %>% 
  filter(nr_words<8,name!="Ahvenanmaa") %>%
  mutate(name=fct_reorder(name,n,.fun=max)) %>%
  uncount(n) %>%
  ggplot(aes(x=nr_words,y=name)) +
  stat_binline(binwidth=1,scale=0.9) +
  theme_hsci_discrete(base_family="Arial") +
  scale_x_continuous(breaks=seq(0,10,by=2)) +
  xlab("Number of words") +
  ylab("Verses") +
#  scale_y_continuous(labels=scales::percent_format()) +
  labs(title="Number of words in verse lines")

Number of characters in words by their position

verse_nr_words <- word_occ %>% 
  group_by(v_id) %>%
  summarise(nr_words=max(pos)) %>%
  compute_a(unique_indexes=list(c("v_id","nr_words")))

word_nr_characters <- words %>%
  mutate(nr_characters=str_length(text)) %>%
  select(w_id,nr_characters) %>%
  compute_a(unique_indexes=list(c("w_id","nr_characters")))

d <- word_occ %>%
  left_join(word_nr_characters) %>%
  left_join(verse_nr_words) %>%
  left_join(verse_poem %>% select(-pos),by=c("v_id")) %>% 
  left_join(poems) %>% 
  count(collection,nr_words,pos,nr_characters) %>%
  collect()
d %>%
  group_by(collection,nr_words,pos) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(nr_words>=2L,nr_words<=5L) %>%
  mutate(nr_words=as_factor(nr_words),pos=as_factor(pos)) %>%
  uncount(n) %>%
  ggplot(aes(x=nr_characters,y=nr_words,fill=pos)) +
  stat_binline(binwidth=1) +
  facet_grid(collection~pos,labeller = labeller(pos=label_both)) + 
  xlab(\Number of characters in word\) +
  ylab(\Number of words in verse\) +
  labs(
    title=\Number of characters in words by their position\,
    subtitle=\According to length of verse and collection\
    ) +
  guides(fill=\none\) +
  theme_hsci_discrete(base_family=\Arial\)

d %>%
  group_by(collection,nr_words,pos) %>%
  mutate(prop=n/sum(n)) %>%
  ungroup() %>%
  filter(nr_words>=2L,nr_words<=5L) %>%
  mutate(nr_words=as_factor(nr_words),pos=as_factor(pos)) %>%
  uncount(n) %>%
  ggplot(aes(x=nr_characters,y=pos,fill=nr_words)) +
  stat_binline(binwidth=1) +
  facet_grid(collection~nr_words,labeller = labeller(nr_words=label_both)) + 
  xlab(\Number of characters in word\) +
  ylab(\Position\) +
  labs(
    title=\Number of characters in words by their position\,
    subtitle=\According to length of verse and collection\
    ) +
  guides(fill=\none\) +
  theme_hsci_discrete(base_family=\Arial\)

LS0tCnRpdGxlOiAiR2VuZXJhbCBzdGF0aXN0aWNhbCBvdmVydmlld3Mgb2YgRklMVEVSIGRhdGEiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChtZXNzYWdlPUZBTFNFLGRwaT0zMDAsZmlnLnJldGluYT0yLGZpZy53aWR0aD04KQpzb3VyY2UoaGVyZTo6aGVyZSgic3JjL2NvbW1vbl9iYXNpcy5SIikpCnRtYXBfbW9kZSgicGxvdCIpCmBgYAoKIyBUZW1wb3JhbCBvdmVydmlldwoKYGBge3J9CnBfeWVhciAlPiUgCiAgaW5uZXJfam9pbihwb2VtcyxieT1jKCJwX2lkIikpICU+JQogIGNvdW50KGNvbGxlY3Rpb24seWVhcikgJT4lCiAgbXV0YXRlKG1lYXN1cmU9InllYXJseSBjb3VudCIpICU+JQogIHVuaW9uX2FsbCgKICAgIHBfeWVhciAlPiUgIyAxMCB5ZWFyIHJvbGxpbmcgbWVhbgogICAgICBkaXN0aW5jdCh5ZWFyKSAlPiUgCiAgICAgIGxlZnRfam9pbihwX3llYXIgJT4lIGRpc3RpbmN0KHllYXIpLHNxbF9vbj0iUkhTLnllYXIgQkVUV0VFTiBMSFMueWVhci01IEFORCBMSFMueWVhcis0IikgJT4lCiAgICAgIGlubmVyX2pvaW4ocF95ZWFyLGJ5PWMoInllYXIueSI9InllYXIiKSkgJT4lCiAgICAgIGlubmVyX2pvaW4ocG9lbXMsYnk9YygicF9pZCIpKSAlPiUKICAgICAgZ3JvdXBfYnkoY29sbGVjdGlvbj1jb2xsZWN0aW9uLHllYXI9eWVhci54KSAlPiUKICAgICAgc3VtbWFyaXplKG49bigpL25fZGlzdGluY3QoeWVhci55KSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgICAgIG11dGF0ZShtZWFzdXJlPSIxMCB5ZWFyIHJvbGxpbmcgbWVhbiIpCiAgKSAlPiUKICBmaWx0ZXIoY29sbGVjdGlvbiE9ImxpdGVyYXJ5IiwheWVhciAlaW4lIGMoMCw5OTk5KSkgJT4lCiAgbXV0YXRlKHllYXI9aWZfZWxzZSh5ZWFyPj0xODAwLHllYXIsMTc4MCkpICU+JQogIGdyb3VwX2J5KGNvbGxlY3Rpb24sbWVhc3VyZSx5ZWFyKSAlPiUKICBzdW1tYXJpc2Uobj1zdW0obiksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGNvbGxlY3QoKSAlPiUKICBjb21wbGV0ZSh5ZWFyLGNvbGxlY3Rpb24sbWVhc3VyZSxmaWxsPWxpc3Qobj0wKSkgJT4lCiAgbXV0YXRlKGNvbGxlY3Rpb249ZmN0X3JlbGV2ZWwoc3RyX3RvX3VwcGVyKGNvbGxlY3Rpb24pLCJFUkFCIiwiU0tWUiIsIkpSIikpICU+JQogIGdyb3VwX2J5KGNvbGxlY3Rpb24sbWVhc3VyZSkgJT4lCiAgYXJyYW5nZSh5ZWFyKSAlPiUKICBmaWx0ZXIobiE9MCB8IGxhZyhuKSE9MCB8IGxlYWQobikhPTApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoeW91dGxpZXI9bj40NjAwLHhvdXRsaWVyPXllYXI8MTgwMCkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIseT1uLGNvbG9yPWNvbGxlY3Rpb24pKSArCiAgZ2VvbV9wb2ludChkYXRhPX4ueCAlPiUgZmlsdGVyKG1lYXN1cmU9PSJ5ZWFybHkgY291bnQiLHlvdXRsaWVyPT1GQUxTRSksc2l6ZT0wLjUpICsKICBnZW9tX3BvaW50KGRhdGE9fi54ICU+JSBmaWx0ZXIoeW91dGxpZXI9PVRSVUUpLGFlcyh4PXllYXIpLHk9NTAwMCkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhPX4ueCAlPiUgZmlsdGVyKHlvdXRsaWVyPT1UUlVFKSxhZXMoeD15ZWFyLGxhYmVsPXNjYWxlczo6bnVtYmVyKG4pKSx5PTUwMDAsIHNob3cubGVnZW5kPUZBTFNFKSArCiAgZ2VvbV9wb2ludChkYXRhPX4ueCAlPiUgZmlsdGVyKHhvdXRsaWVyPT1UUlVFLG1lYXN1cmU9PSJ5ZWFybHkgY291bnQiKSxhZXMoeD15ZWFyLHk9bikpICsKICBnZW9tX3RleHRfcmVwZWwoZGF0YT1+LnggJT4lIGZpbHRlcih4b3V0bGllcj09VFJVRSxtZWFzdXJlPT0ieWVhcmx5IGNvdW50IiksYWVzKHg9eWVhcix5PW4sbGFiZWw9c2NhbGVzOjpudW1iZXIobikpLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAgCiAgZ2VvbV9saW5lKGRhdGE9fi54ICU+JSBmaWx0ZXIoeG91dGxpZXI9PUZBTFNFLG1lYXN1cmU9PSIxMCB5ZWFyIHJvbGxpbmcgbWVhbiIpKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKSArIAogIHRoZW1lKAogICAgbGVnZW5kLmp1c3RpZmljYXRpb249YygwLDEpLCAKICAgIGxlZ2VuZC5wb3NpdGlvbj1jKDAuMDIsIDAuOTgpLCAKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgIGxlZ2VuZC5rZXk9ZWxlbWVudF9ibGFuaygpCiAgKSArIAogIGxhYnMoY29sb3I9TlVMTCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCw0NjAwKSx4bGltPWMoMTgwMCwxOTcwKSxjbGlwPSJvZmYiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwyMDAwMCxieT0xMDAwKSxsYWJlbHM9c2NhbGVzOjpudW1iZXIpICsKIyAgeWxhYigiUG9lbXMiKSArCiAgeWxhYigiUnVub2plbiBtw6TDpHLDpCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgxMDAwLDIwMDAsYnk9MTApKSArCiMgIHhsYWIoIlllYXIiKSArCiAgeGxhYigiVnVvc2kiKSArCiAgZ2d0aXRsZSgiIikKIyAgZ2d0aXRsZSgiUnVub2plbiBtw6TDpHLDpCB2dW9zaXR0YWluIGphIGtva29lbG1pdHRhaW4iKQojICBnZ3RpdGxlKCJOdW1iZXIgb2YgcG9lbXMgYnkgeWVhciBhbmQgY29sbGVjdGlvbiIpCmBgYAoKYGBge3J9CnRvcF90b3BfdGhlbWVzIDwtIHBvZW1fdGhlbWUgJT4lIAogIGlubmVyX2pvaW4ocG9lbXMpICU+JQogIGlubmVyX2pvaW4odGhlbWVzX3RvX3RvcF9sZXZlbF90aGVtZXMpICU+JQogIGNvdW50KGNvbGxlY3Rpb24sIGFuY2VzdG9yX3RfaWQpICU+JQogIGdyb3VwX2J5KGNvbGxlY3Rpb24pICU+JQogIHNsaWNlX21heChuLG49OSkgJT4lCiAgdW5ncm91cCgpICU+JSAKICBtdXRhdGUodG9wX3RoZW1lPVRSVUUpICU+JQogIHNlbGVjdChhbmNlc3Rvcl90X2lkLHRvcF90aGVtZSkgJT4lCiAgY29tcHV0ZV9hKHRlbXBvcmFyeT1UUlVFLCBvdmVyd3JpdGU9VFJVRSkKYGBgCgoKYGBge3J9CmQgPC0gcF95ZWFyICU+JSAKICBpbm5lcl9qb2luKHBvZW1zLGJ5PWMoInBfaWQiKSkgJT4lCiAgaW5uZXJfam9pbihwb2VtX3RoZW1lICU+JQogICAgaW5uZXJfam9pbih0aGVtZXNfdG9fdG9wX2xldmVsX3RoZW1lcyAlPiUgCiAgICAgICAgICAgICAgICAgaW5uZXJfam9pbih0aGVtZXMgJT4lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcighc3RyX2RldGVjdCh0aGVtZV9pZCwiXmVyYWJfb3JpZyIpKSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZWN0KGFuY2VzdG9yX3RfaWQ9dF9pZCxhbmNlc3Rvcl90aGVtZV9uYW1lPW5hbWUpKSkpICU+JQogIGxlZnRfam9pbih0b3BfdG9wX3RoZW1lcykgJT4lCiAgbXV0YXRlKAogICAgYW5jZXN0b3JfdGhlbWVfbmFtZT1pZl9lbHNlKCFpcy5uYSh0b3BfdGhlbWUpLGFuY2VzdG9yX3RoZW1lX25hbWUsIk11dXQiKSwKICAgIGFuY2VzdG9yX3RfaWQ9aWZfZWxzZSghaXMubmEodG9wX3RoZW1lKSxhbmNlc3Rvcl90X2lkLC0xKSwKICAgICkgJT4lCiAgcmVwbGFjZV9uYShsaXN0KGFuY2VzdG9yX3RoZW1lX25hbWU9IlR1bnRlbWF0b24iLCBhbmNlc3Rvcl90X2lkPS0yKSkgJT4lCiAgZGlzdGluY3QoYW5jZXN0b3JfdF9pZCxhbmNlc3Rvcl90aGVtZV9uYW1lLCBjb2xsZWN0aW9uLCB5ZWFyLCBwX2lkKSAlPiUKICBjb3VudChhbmNlc3Rvcl90X2lkLGFuY2VzdG9yX3RoZW1lX25hbWUsIGNvbGxlY3Rpb24sIHllYXIpICU+JQogIG11dGF0ZShtZWFzdXJlPSJ5ZWFybHkgY291bnQiKSAlPiUKICB1bmlvbl9hbGwoCiAgICBwX3llYXIgJT4lICMgMTAgeWVhciByb2xsaW5nIG1lYW4KICAgICAgZGlzdGluY3QoeWVhcikgJT4lIAogICAgICBsZWZ0X2pvaW4ocF95ZWFyICU+JSBkaXN0aW5jdCh5ZWFyKSxzcWxfb249IlJIUy55ZWFyIEJFVFdFRU4gTEhTLnllYXItNSBBTkQgTEhTLnllYXIrNCIpICU+JQogICAgICBpbm5lcl9qb2luKHBfeWVhcixieT1jKCJ5ZWFyLnkiPSJ5ZWFyIikpICU+JQogICAgICBpbm5lcl9qb2luKHBvZW1zLGJ5PWMoInBfaWQiKSkgJT4lCiAgICAgIGlubmVyX2pvaW4ocG9lbV90aGVtZSAlPiUKICAgICAgICBpbm5lcl9qb2luKHRoZW1lc190b190b3BfbGV2ZWxfdGhlbWVzICU+JSAKICAgICAgICAgICAgICAgICAgICAgaW5uZXJfam9pbih0aGVtZXMgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyKCFzdHJfZGV0ZWN0KHRoZW1lX2lkLCJeZXJhYl9vcmlnIikpICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGVjdChhbmNlc3Rvcl90X2lkPXRfaWQsYW5jZXN0b3JfdGhlbWVfbmFtZT1uYW1lKSkpKSAlPiUKICAgICAgbGVmdF9qb2luKHRvcF90b3BfdGhlbWVzKSAlPiUKICAgICAgbXV0YXRlKAogICAgICAgIGFuY2VzdG9yX3RoZW1lX25hbWU9aWZfZWxzZSghaXMubmEodG9wX3RoZW1lKSxhbmNlc3Rvcl90aGVtZV9uYW1lLCJNdXV0IiksCiAgICAgICAgYW5jZXN0b3JfdF9pZD1pZl9lbHNlKCFpcy5uYSh0b3BfdGhlbWUpLGFuY2VzdG9yX3RfaWQsLTEpLAogICAgICAgICkgJT4lCiAgICAgIHJlcGxhY2VfbmEobGlzdChhbmNlc3Rvcl90aGVtZV9uYW1lPSJUdW50ZW1hdG9uIiwgYW5jZXN0b3JfdF9pZD0tMikpICU+JQogICAgICBkaXN0aW5jdChhbmNlc3Rvcl90X2lkLGFuY2VzdG9yX3RoZW1lX25hbWUsIGNvbGxlY3Rpb24sIHllYXIueCwgeWVhci55LCBwX2lkKSAlPiUKICAgICAgZ3JvdXBfYnkoYW5jZXN0b3JfdF9pZCxhbmNlc3Rvcl90aGVtZV9uYW1lLCBjb2xsZWN0aW9uLCB5ZWFyPXllYXIueCkgJT4lCiAgICAgIHN1bW1hcml6ZShuPW4oKS9uX2Rpc3RpbmN0KHllYXIueSksLmdyb3Vwcz0iZHJvcCIpICU+JQogICAgICBtdXRhdGUobWVhc3VyZT0iMTAgeWVhciByb2xsaW5nIG1lYW4iKQogICkgJT4lCiAgZmlsdGVyKGNvbGxlY3Rpb24hPSJsaXRlcmFyeSIsIXllYXIgJWluJSBjKDBMLDk5OTlMKSkgJT4lCiAgbXV0YXRlKHllYXI9aWZfZWxzZSh5ZWFyPj0xODAwTCx5ZWFyLDE3ODBMKSkgJT4lCiAgZ3JvdXBfYnkoYW5jZXN0b3JfdGhlbWVfbmFtZSwgY29sbGVjdGlvbiwgbWVhc3VyZSwgeWVhcikgJT4lCiAgc3VtbWFyaXNlKG49c3VtKG4pLC5ncm91cHM9ImRyb3AiKSAlPiUKICBjb2xsZWN0KCkKYGBgCgpgYGB7cn0KZCAlPiUKICBtdXRhdGUoY29sbGVjdGlvbj1mY3RfcmVsZXZlbChzdHJfdG9fdXBwZXIoY29sbGVjdGlvbiksIlNLVlIiLCJFUkFCIiwiSlIiKSkgJT4lCiAgZmlsdGVyKGNvbGxlY3Rpb249PSJTS1ZSIikgJT4lCiAgY29tcGxldGUoYW5jZXN0b3JfdGhlbWVfbmFtZSwgeWVhcixjb2xsZWN0aW9uLG1lYXN1cmUsZmlsbD1saXN0KG49MCkpICU+JQogIGdyb3VwX2J5KGFuY2VzdG9yX3RoZW1lX25hbWUsIGNvbGxlY3Rpb24sbWVhc3VyZSkgJT4lCiAgYXJyYW5nZSh5ZWFyKSAlPiUKICBmaWx0ZXIobiE9MCB8IGxhZyhuKSE9MCB8IGxlYWQobikhPTApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoeW91dGxpZXI9bj4xMzAwLHhvdXRsaWVyPXllYXI8MTgwMCkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIseT1uLGNvbG9yPWFuY2VzdG9yX3RoZW1lX25hbWUpKSArCiMgIGZhY2V0X3dyYXAofmNvbGxlY3Rpb24pICsKICBnZW9tX3BvaW50KGRhdGE9fi54ICU+JSBmaWx0ZXIobWVhc3VyZT09InllYXJseSBjb3VudCIseW91dGxpZXI9PUZBTFNFLHhvdXRsaWVyPT1GQUxTRSksc2l6ZT0wLjUpICsKICBnZW9tX3BvaW50KGRhdGE9fi54ICU+JSBmaWx0ZXIoeW91dGxpZXI9PVRSVUUpLGFlcyh4PXllYXIpLHk9MTQwMCkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhPX4ueCAlPiUgZmlsdGVyKHlvdXRsaWVyPT1UUlVFKSxhZXMoeD15ZWFyLGxhYmVsPXNjYWxlczo6bnVtYmVyKG4pKSx5PTE0MDAsIHNob3cubGVnZW5kPUZBTFNFKSArCiAgZ2VvbV9wb2ludChkYXRhPX4ueCAlPiUgZmlsdGVyKHhvdXRsaWVyPT1UUlVFLG1lYXN1cmU9PSJ5ZWFybHkgY291bnQiKSxhZXMoeD0xNzg1LHk9bikpICsKICBnZW9tX3RleHRfcmVwZWwoZGF0YT1+LnggJT4lIGZpbHRlcih4b3V0bGllcj09VFJVRSxtZWFzdXJlPT0ieWVhcmx5IGNvdW50IiksYWVzKHg9MTc4NSx5PW4sbGFiZWw9c2NhbGVzOjpudW1iZXIobikpLCBzaG93LmxlZ2VuZD1GQUxTRSkgKyAgCiAgZ2VvbV9saW5lKGRhdGE9fi54ICU+JSBmaWx0ZXIoeG91dGxpZXI9PUZBTFNFLG1lYXN1cmU9PSIxMCB5ZWFyIHJvbGxpbmcgbWVhbiIpKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKSArIAogIHRoZW1lKAogICAgbGVnZW5kLmp1c3RpZmljYXRpb249YygwLDEpLCAKICAgIGxlZ2VuZC5wb3NpdGlvbj1jKDAuMDIsIDAuOTgpLCAKICAgIGxlZ2VuZC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCAKICAgIGxlZ2VuZC5rZXk9ZWxlbWVudF9ibGFuaygpCiAgKSArIAogIGxhYnMoY29sb3I9TlVMTCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltPWMoMCwxMzAwKSx4bGltPWMoMTgwMCwxOTQwKSxjbGlwPSJvZmYiKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcz1zZXEoMCwyMDAwMCxieT01MDApLGxhYmVscz1zY2FsZXM6Om51bWJlcikgKwojICB5bGFiKCJQb2VtcyIpICsKICB5bGFiKCJSdW5vamVuIG3DpMOkcsOkIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDEwMDAsMjAwMCxieT0xMCkpICsKIyAgeGxhYigiWWVhciIpICsKICB4bGFiKCJWdW9zaSIpICsKICBnZ3RpdGxlKCIiKQojICBnZ3RpdGxlKCJSdW5vamVuIG3DpMOkcsOkIHZ1b3NpdHRhaW4gamEga29rb2VsbWl0dGFpbiIpCiMgIGdndGl0bGUoIk51bWJlciBvZiBwb2VtcyBieSB5ZWFyIGFuZCBjb2xsZWN0aW9uIikKYGBgCgpgYGB7cn0KZCAlPiUKICBtdXRhdGUoY29sbGVjdGlvbj1mY3RfcmVsZXZlbChzdHJfdG9fdXBwZXIoY29sbGVjdGlvbiksIlNLVlIiLCJFUkFCIikpICU+JQogIGZpbHRlcihjb2xsZWN0aW9uPT0iRVJBQiIpICU+JQogIGNvbXBsZXRlKGFuY2VzdG9yX3RoZW1lX25hbWUsIHllYXIsY29sbGVjdGlvbixtZWFzdXJlLGZpbGw9bGlzdChuPTApKSAlPiUKICBncm91cF9ieShhbmNlc3Rvcl90aGVtZV9uYW1lLCBjb2xsZWN0aW9uLG1lYXN1cmUpICU+JQogIGFycmFuZ2UoeWVhcikgJT4lCiAgZmlsdGVyKG4hPTAgfCBsYWcobikhPTAgfCBsZWFkKG4pIT0wKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKHlvdXRsaWVyPW4+ODIwLHhvdXRsaWVyPXllYXI8MTgwMCkgJT4lCiAgbXV0YXRlKGFuY2VzdG9yX3RoZW1lX25hbWU9Y2FzZV9tYXRjaChhbmNlc3Rvcl90aGVtZV9uYW1lLAogICAgIkxhdWx1ZCBub29ycmFodmEgZWx1c3QiIH4gIkxhdWx1dCBudW9yaXNvbiBlbMOkbcOkc3TDpCAoTGF1bHVkIG5vb3JyYWh2YSBlbHVzdCkiLAogICAgIk11dXQiIH4gIk11dXQgKHNpc8OkbHTDpMOkIDE3IGx1b2trYWEpIiwKICAgICJMYXVsdWQgbWVlbGVsYWh1dGFtaXNla3MiIH4gIlZpaWhkeXR5c2xhdWx1dCAoTGF1bHVkIG1lZWxlbGFodXRhbWlzZWtzKSIsCiAgICAiTMO8cm9lZXBpbGlzZWQgbGF1bHVkIiB+ICJMeXJvZWVwcGlzZXQgbGF1bHV0IChMw7xyb2VlcGlsaXNlZCBsYXVsdWQpIiwKICAgICJMYXVsdWQgbGF1bHVzdCIgfiAiTGF1bHV0IGxhdWx1c3RhIChMYXVsdWQgbGF1bHVzdCkiLAogICAgIlTDtsO2bGF1bHVkIiB+ICJUecO2bGF1bHV0IChUw7bDtmxhdWx1ZCkiLAogICAgIkxvb2R1c2xhdWx1ZCIgfiAiTGF1bHV0IGx1b25ub3N0YSAoTG9vZHVzbGF1bHVkKSIsCiAgICAiTGF1bHVkIMO8aGlza29uZGxpa2VzdCB2YWhla29yZGFkZXN0IiB+ICJMYXVsdXQgeWh0ZWlza3VubmFsbGlzaXN0YSBzdWh0ZWlzdGFcbihMYXVsdWQgw7xoaXNrb25kbGlrZXN0IHZhaGVrb3JkYWRlc3QpIiwKICAgICJNdXJlbGF1bHVkIiB+ICJIdW9saWxhdWx1dCAoTXVyZWxhdWx1ZCkiLAogICAgIkxhdWx1ZCBhYmllbHVzdCIgfiAiTGF1bHV0IGF2aW9lbMOkbcOkc3TDpCAoTGF1bHVkIGFiaWVsdXN0KSIsCiAgICAiS2FsZW5kcmlsYXVsdWQiIH4gIkthbGVuZGFhcmlsYXVsdXQgKEthbGVuZHJpbGF1bHVkKSIKICApKSAlPiUKICBtdXRhdGUoYW5jZXN0b3JfdGhlbWVfbmFtZT1mY3RfcmVvcmRlcihhbmNlc3Rvcl90aGVtZV9uYW1lLG4sLmZ1bj1zdW0sLmRlc2M9VFJVRSkpICU+JQogIG11dGF0ZShhbmNlc3Rvcl90aGVtZV9uYW1lPWZjdF9yZWxldmVsKGFuY2VzdG9yX3RoZW1lX25hbWUsICJNdXV0IChzaXPDpGx0w6TDpCAxNyBsdW9ra2FhKSIsIGFmdGVyPUluZikpICU+JQogIGdncGxvdChhZXMoeD15ZWFyLHk9bixjb2xvcj1hbmNlc3Rvcl90aGVtZV9uYW1lKSkgKwojICBmYWNldF93cmFwKH5jb2xsZWN0aW9uKSArCiAgZ2VvbV9wb2ludChkYXRhPX4ueCAlPiUgZmlsdGVyKG1lYXN1cmU9PSJ5ZWFybHkgY291bnQiLHlvdXRsaWVyPT1GQUxTRSx4b3V0bGllcj09RkFMU0UpLHNpemU9MC41KSArCiAgZ2VvbV9wb2ludChkYXRhPX4ueCAlPiUgZmlsdGVyKHlvdXRsaWVyPT1UUlVFKSxhZXMoeD15ZWFyKSx5PTkwMCkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhPX4ueCAlPiUgZmlsdGVyKHlvdXRsaWVyPT1UUlVFKSxhZXMoeD15ZWFyLGxhYmVsPXNjYWxlczo6bnVtYmVyKG4pKSx5PTkwMCwgc2hvdy5sZWdlbmQ9RkFMU0UpICsKICBnZW9tX3BvaW50KGRhdGE9fi54ICU+JSBmaWx0ZXIoeG91dGxpZXI9PVRSVUUsbWVhc3VyZT09InllYXJseSBjb3VudCIpLGFlcyh4PTE3ODUseT1uKSkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhPX4ueCAlPiUgZmlsdGVyKHhvdXRsaWVyPT1UUlVFLG1lYXN1cmU9PSJ5ZWFybHkgY291bnQiKSxhZXMoeD0xNzg1LHk9bixsYWJlbD1zY2FsZXM6Om51bWJlcihuKSksIHNob3cubGVnZW5kPUZBTFNFKSArICAKICBnZW9tX2xpbmUoZGF0YT1+LnggJT4lIGZpbHRlcih4b3V0bGllcj09RkFMU0UsbWVhc3VyZT09IjEwIHllYXIgcm9sbGluZyBtZWFuIikpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsgCiAgdGhlbWUoCiAgICBsZWdlbmQuanVzdGlmaWNhdGlvbj1jKDAsMSksIAogICAgbGVnZW5kLnBvc2l0aW9uPWMoMC4wMiwgMC45OCksIAogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgbGVnZW5kLmtleT1lbGVtZW50X2JsYW5rKCkKICApICsgCiAgbGFicyhjb2xvcj1OVUxMKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDgyMCkseGxpbT1jKDE4MjAsMTk1MCksY2xpcD0ib2ZmIikgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3M9c2VxKDAsMjAwMDAsYnk9MjAwKSxsYWJlbHM9c2NhbGVzOjpudW1iZXIpICsKIyAgeWxhYigiUG9lbXMiKSArCiAgeWxhYigiUnVub2plbiBtw6TDpHLDpCIpICsKIyAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChucm93PTIpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcz1zZXEoMTAwMCwyMDAwLGJ5PTEwKSkgKwojICB4bGFiKCJZZWFyIikgKwogIHhsYWIoIlZ1b3NpIikgKwogIGdndGl0bGUoIiIpCiMgIGdndGl0bGUoIlJ1bm9qZW4gbcOkw6Ryw6QgdnVvc2l0dGFpbiBqYSBrb2tvZWxtaXR0YWluIikKIyAgZ2d0aXRsZSgiTnVtYmVyIG9mIHBvZW1zIGJ5IHllYXIgYW5kIGNvbGxlY3Rpb24iKQpgYGAKCmBgYHtyfQpkICU+JQogIG11dGF0ZShjb2xsZWN0aW9uPWZjdF9yZWxldmVsKHN0cl90b191cHBlcihjb2xsZWN0aW9uKSwiU0tWUiIsIkVSQUIiLCJKUiIpKSAlPiUKICBmaWx0ZXIoY29sbGVjdGlvbj09IkpSIikgJT4lCiAgY29tcGxldGUoYW5jZXN0b3JfdGhlbWVfbmFtZSwgeWVhcixjb2xsZWN0aW9uLG1lYXN1cmUsZmlsbD1saXN0KG49MCkpICU+JQogIGdyb3VwX2J5KGFuY2VzdG9yX3RoZW1lX25hbWUsIGNvbGxlY3Rpb24sbWVhc3VyZSkgJT4lCiAgYXJyYW5nZSh5ZWFyKSAlPiUKICBmaWx0ZXIobiE9MCB8IGxhZyhuKSE9MCB8IGxlYWQobikhPTApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBtdXRhdGUoeW91dGxpZXI9bj42NTAwLHhvdXRsaWVyPXllYXI8MTgwMCkgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIseT1uLGNvbG9yPWFuY2VzdG9yX3RoZW1lX25hbWUpKSArCiMgIGZhY2V0X3dyYXAofmNvbGxlY3Rpb24pICsKICBnZW9tX3BvaW50KGRhdGE9fi54ICU+JSBmaWx0ZXIobWVhc3VyZT09InllYXJseSBjb3VudCIseW91dGxpZXI9PUZBTFNFKSxzaXplPTAuNSkgKwogIGdlb21fcG9pbnQoZGF0YT1+LnggJT4lIGZpbHRlcih5b3V0bGllcj09VFJVRSksYWVzKHg9eWVhcikseT03MjAwKSArCiAgZ2VvbV90ZXh0X3JlcGVsKGRhdGE9fi54ICU+JSBmaWx0ZXIoeW91dGxpZXI9PVRSVUUpLGFlcyh4PXllYXIsbGFiZWw9c2NhbGVzOjpudW1iZXIobikpLHk9NzIwMCwgc2hvdy5sZWdlbmQ9RkFMU0UpICsKICBnZW9tX3BvaW50KGRhdGE9fi54ICU+JSBmaWx0ZXIoeG91dGxpZXI9PVRSVUUsbWVhc3VyZT09InllYXJseSBjb3VudCIpLGFlcyh4PXllYXIseT1uKSkgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhPX4ueCAlPiUgZmlsdGVyKHhvdXRsaWVyPT1UUlVFLG1lYXN1cmU9PSJ5ZWFybHkgY291bnQiKSxhZXMoeD15ZWFyLHk9bixsYWJlbD1zY2FsZXM6Om51bWJlcihuKSksIHNob3cubGVnZW5kPUZBTFNFKSArICAKICBnZW9tX2xpbmUoZGF0YT1+LnggJT4lIGZpbHRlcih4b3V0bGllcj09RkFMU0UsbWVhc3VyZT09IjEwIHllYXIgcm9sbGluZyBtZWFuIikpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsgCiAgdGhlbWUoCiAgICBsZWdlbmQuanVzdGlmaWNhdGlvbj1jKDAsMSksIAogICAgbGVnZW5kLnBvc2l0aW9uPWMoMC4wMiwgMC45OCksIAogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIAogICAgbGVnZW5kLmtleT1lbGVtZW50X2JsYW5rKCkKICApICsgCiAgbGFicyhjb2xvcj1OVUxMKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW09YygwLDY1MDApLHhsaW09YygxODAwLDE5NjApLGNsaXA9Im9mZiIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDIwMDAwLGJ5PTEwMDApLGxhYmVscz1zY2FsZXM6Om51bWJlcikgKwojICB5bGFiKCJQb2VtcyIpICsKICB5bGFiKCJSdW5vamVuIG3DpMOkcsOkIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDEwMDAsMjAwMCxieT0xMCkpICsKIyAgeGxhYigiWWVhciIpICsKICB4bGFiKCJWdW9zaSIpICsKICBnZ3RpdGxlKCIiKQojICBnZ3RpdGxlKCJSdW5vamVuIG3DpMOkcsOkIHZ1b3NpdHRhaW4gamEga29rb2VsbWl0dGFpbiIpCiMgIGdndGl0bGUoIk51bWJlciBvZiBwb2VtcyBieSB5ZWFyIGFuZCBjb2xsZWN0aW9uIikKYGBgCgoKYGBge3J9CnBfeWVhciAlPiUgCiAgZmlsdGVyKHllYXIgJWluJSBjKDAsOTk5OSkpICU+JSAKICBsZWZ0X2pvaW4ocG9lbXMpICU+JSAKICBjb3VudChjb2xsZWN0aW9uLHllYXIpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBndCgpICU+JQogIHRhYl9oZWFkZXIodGl0bGU9IkFibm9ybWFsIHllYXJzIikgJT4lCiAgZm10X2ludGVnZXIobikKYGBgCgojIE92ZXJ2aWV3IG9mIGNvbGxlY3RvcnMKCmBgYHtyIGNvbGxlY3RvcnNfb3ZlcnZpZXcsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTExfQpwb2VtcyAlPiUgCiAgZGlzdGluY3QoY29sbGVjdGlvbikgJT4lCiAgcHVsbCgpICU+JQogIG1hcCh+cF9jb2wgJT4lIAogICAgaW5uZXJfam9pbihwb2VtcyAlPiUgZmlsdGVyKGNvbGxlY3Rpb249PS54KSxieT1jKCJwX2lkIikpICU+JQogICAgY291bnQoY29sX2lkKSAlPiUKICAgIGxlZnRfam9pbihjb2xsZWN0b3JzLGJ5PWMoImNvbF9pZCIpKSAlPiUKICAgIHNlbGVjdChjb2xfaWQsbmFtZSxuKSAlPiUKICAgIGNvbGxlY3QoKSAlPiUKICAgIG11dGF0ZShjb2xfaWQ9ZmN0X3Jlb3JkZXIoc3RyX2MoY29sX2lkLCJ8IixuYW1lKSxuKSkgJT4lCiAgICBtdXRhdGUoY29sX2lkPWZjdF9sdW1wX24oY29sX2lkLG49MTAwLHc9bikpICU+JQogICAgbXV0YXRlKGNvbF9pZD1mY3RfcmVsZXZlbChjb2xfaWQsIk90aGVyIikpICU+JQogICAgZ3JvdXBfYnkoY29sX2lkKSAlPiUKICAgIHRhbGx5KHd0PW4pICU+JSB7CiAgICAgIGdncGxvdCguLGFlcyh4PWNvbF9pZCx5PW4pKSArCiAgICAgIGdlb21fY29sKCkgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsPXAobikpLGhqdXN0PSdsZWZ0JyxudWRnZV95ID0gMTAwKSArCiAgICAgIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogICAgICBjb29yZF9mbGlwKCkgKwogICAgICBsYWJzKHRpdGxlPXN0cl9jKCJDb2xsZWN0b3JzIGluICIsLngpKQogICAgfQogICkKYGBgCgpgYGB7cn0KcF9jb2wgJT4lIAogIGFudGlfam9pbihjb2xsZWN0b3JzKSAlPiUKICBjb3VudChjb2xfaWQpICU+JQogIGd0KCkgJT4lCiAgdGFiX2hlYWRlcih0aXRsZT0iQ29sbGVjdG9ycyB3aXRob3V0IGEgbmFtZSIpICU+JQogIGZtdF9pbnRlZ2VyKG4pCmBgYAoKYGBge3J9CnBfY29sICU+JQogIGlubmVyX2pvaW4oY29sbGVjdG9ycykgJT4lCiAgaW5uZXJfam9pbihwb2VtcykgJT4lCiAgZmlsdGVyKGNvbGxlY3Rpb24hPSJsaXRlcmFyeSIpICU+JQogIG11dGF0ZShjb2xsZWN0aW9uPXN0cl90b191cHBlcihjb2xsZWN0aW9uKSkgJT4lCiAgY291bnQoY29sbGVjdGlvbixjb2xfaWQsbmFtZSkgJT4lCiAgZ3JvdXBfYnkoY29sbGVjdGlvbikgJT4lCiAgc2xpY2VfbWF4KG9yZGVyX2J5PW4sbj0xMCkgJT4lCiAgdW5ncm91cCgpICU+JQogIHNlbGVjdCgtY29sX2lkKSAlPiUKICBndChncm91cG5hbWVfY29sID0gImNvbGxlY3Rpb24iLCByb3duYW1lX2NvbCA9ICJuYW1lIikgJT4lCiAgcm93X2dyb3VwX29yZGVyKGMoIkVSQUIiLCJTS1ZSIiwiSlIiKSkgJT4lCiAgZm10X2ludGVnZXIobixzZXBfbWFyaz0iICIpCmBgYAoKYGBge3IsZmlnLmhlaWdodD0zfQpwX2NvbCAlPiUKICBpbm5lcl9qb2luKGNvbGxlY3RvcnMpICU+JQogIGlubmVyX2pvaW4ocG9lbXMpICU+JQogIGZpbHRlcihjb2xsZWN0aW9uIT0ibGl0ZXJhcnkiKSAlPiUKICBtdXRhdGUoY29sbGVjdGlvbj1zdHJfdG9fdXBwZXIoY29sbGVjdGlvbikpICU+JQogIGNvdW50KGNvbGxlY3Rpb24sY29sX2lkLG5hbWUpICU+JQogIGdyb3VwX2J5KGNvbGxlY3Rpb24pICU+JQogIHNsaWNlX21heChvcmRlcl9ieT1uLG49MTApICU+JQogIHVuZ3JvdXAoKSAlPiUKICBpbm5lcl9qb2luKHBfY29sKSAlPiUKICBpbm5lcl9qb2luKHBvZW1fdGhlbWUpICU+JQogIGlubmVyX2pvaW4odGhlbWVzX3RvX3RvcF9sZXZlbF90aGVtZXMpICU+JQogIGNvdW50KGNvbGxlY3Rpb24sIGNvbF9pZCwgdF9pZD1hbmNlc3Rvcl90X2lkKSAlPiUKICBpbm5lcl9qb2luKHRoZW1lcyAlPiUgcmVuYW1lKHRoZW1lX25hbWU9bmFtZSkpICU+JQogIGlubmVyX2pvaW4oY29sbGVjdG9ycykgJT4lCiAgZmlsdGVyKGNvbGxlY3Rpb249PSJTS1ZSIikgJT4lCiAgY29sbGVjdCgpICU+JSAKIyAgZ3JvdXBfYnkoY29sbGVjdGlvbikgJT4lCiMgIG11dGF0ZSh0aGVtZV9uYW1lPWZjdF9sdW1wX24odGhlbWVfbmFtZSwgbiwgbj01LCBvdGhlcl9sZXZlbD0iTXV1dCIpKSAlPiUKIyAgdW5ncm91cCgpICU+JQogIGdyb3VwX2J5KGNvbF9pZCkgJT4lCiAgbXV0YXRlKHRuPXN1bShuKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIG11dGF0ZShuYW1lPWZjdF9yZW9yZGVyKG5hbWUsdG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bmFtZSxmaWxsPXRoZW1lX25hbWUseT1uKSkgKwojICBmYWNldF93cmFwKH5jb2xsZWN0aW9uLHNjYWxlcz0iZnJlZSIsbmNvbD0xKSArCiAgZ2VvbV9jb2woKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZSgpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpudW1iZXIpICsKICBsYWJzKGZpbGw9IlDDpMOkdHl5cHBpIikgKwogIHhsYWIoIktlcsOkw6Rqw6QiKSArCiAgeWxhYigiVHl5cHBpbWVya2ludMO2asOkIikKCmBgYAoKCiMgR2VvZ3JhcGhpY2FsIG92ZXJ2aWV3CgpgYGB7cn0KZCA8LSBwX2xvYyAlPiUgCiAgY291bnQobG9jX2lkKSAlPiUgCiAgaW5uZXJfam9pbihsb2NhdGlvbnMpICU+JQogIHNlbGVjdChuYW1lLG4pICU+JQogIGNvbGxlY3QoKQoKcG9lbXNfd2l0aG91dF9sb2NhdGlvbiA8LSBwb2VtcyAlPiUgCiAgYW50aV9qb2luKHBfbG9jKSAlPiUgCiAgY291bnQoKSAlPiUgCiAgcHVsbCgpCgp1bnByb2plY3RlZF9sb2NhdGlvbnMgPC0gZCAlPiUKICBhbnRpX2pvaW4ocG9seWdvbnMpICU+JQogIGFkZF9yb3cobmFtZT1OQSxuPXBvZW1zX3dpdGhvdXRfbG9jYXRpb24pCmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTExLHJlc3VsdHM9ImFzaXMifQpwb2x5Z29ucyAlPiUKICBsZWZ0X2pvaW4oZCkgJT4lCiAgdG1fc2hhcGUoKSArCiAgdG1fcG9seWdvbnMoY29sPSduJywgaWQ9J25hbWUnLCBzdHlsZT0nZmlzaGVyJywgcGFsZXR0ZT0ncGxhc21hJykgKwogIHRtX2xheW91dCh0aXRsZT1zdHJfYygiR2VvZ3JhcGhpY2FsIG92ZXJ2aWV3LiBNaXNzaW5nICIsdW5wcm9qZWN0ZWRfbG9jYXRpb25zICU+JSB0YWxseSh3dD1uKSAlPiUgcHVsbCgpICU+JSBwLCIgcG9lbXMuIikpCmBgYAoKIyMgUG9lbSBsb2NhdGlvbnMgbm90IG1hcHBlZAoKYGBge3J9CnVucHJvamVjdGVkX2xvY2F0aW9ucyAlPiUKICBhcnJhbmdlKGRlc2MobikpICU+JQogIGd0KCkgJT4lCiAgdGFiX2hlYWRlcigiUG9lbSBsb2NhdGlvbnMgbm90IG1hcHBlZCIpICU+JQogIGZtdF9pbnRlZ2VyKG4pCmBgYAoKIyMgR2VvZ3JhcGhpY2FsIG92ZXJ2aWV3IGJ5IGNvbGxlY3Rpb24KCmBgYHtyfQpkIDwtIHBfbG9jICU+JSAKICBsZWZ0X2pvaW4ocG9lbXMpICU+JQogIGNvdW50KGNvbGxlY3Rpb24sbG9jX2lkKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGlubmVyX2pvaW4obG9jYXRpb25zKSAlPiUKICBzZWxlY3QoY29sbGVjdGlvbixuYW1lLG4pICU+JQogIGNvbGxlY3QoKQoKcG9lbXNfd2l0aG91dF9sb2NhdGlvbiA8LSBwb2VtcyAlPiUgCiAgYW50aV9qb2luKHBfbG9jKSAlPiUgCiAgY291bnQoY29sbGVjdGlvbikgJT4lIAogIGNvbGxlY3QoKSAlPiUKICBtdXRhdGUobmFtZT1OQV9jaGFyYWN0ZXJfKQoKdW5wcm9qZWN0ZWRfbG9jYXRpb25zIDwtIGQgJT4lCiAgYW50aV9qb2luKHBvbHlnb25zKSAlPiUKICB1bmlvbl9hbGwocG9lbXNfd2l0aG91dF9sb2NhdGlvbikKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD0xMX0KcG9lbXMgJT4lIAogIGRpc3RpbmN0KGNvbGxlY3Rpb24pICU+JQogIHB1bGwoKSAlPiUKICBtYXAofgogICAgdG1fc2hhcGUoCiAgICAgIHBvbHlnb25zICU+JQogICAgICAgIGxlZnRfam9pbigKICAgICAgICAgIHBfbG9jICU+JSAKICAgICAgICAgICAgaW5uZXJfam9pbihwb2VtcyAlPiUgZmlsdGVyKGNvbGxlY3Rpb249PS54KSxieT1jKCJwX2lkIikpICU+JQogICAgICAgICAgICBjb3VudChsb2NfaWQpICU+JSAKICAgICAgICAgICAgaW5uZXJfam9pbihsb2NhdGlvbnMpICU+JQogICAgICAgICAgICBzZWxlY3QobmFtZSxuKSAlPiUKICAgICAgICAgICAgY29sbGVjdCgpCiAgICAgICAgKQogICAgKSArCiAgICB0bV9wb2x5Z29ucyhjb2w9J24nLCBpZD0nbmFtZScsIHN0eWxlPSdmaXNoZXInLCBwYWxldHRlPSdwbGFzbWEnKSArCiAgICB0bV9sYXlvdXQodGl0bGU9c3RyX2MoIkdlb2dyYXBoeSBvZiAiLC54LCIuIE1pc3NpbmcgIix1bnByb2plY3RlZF9sb2NhdGlvbnMgJT4lIGZpbHRlcihjb2xsZWN0aW9uPT0ueCkgJT4lIHRhbGx5KHd0PW4pICU+JSBwdWxsKCkgJT4lIHAsIiBwb2Vtcy4iKSkKICApCmBgYAoKIyMgUG9lbSBsb2NhdGlvbnMgbm90IG1hcHBlZCBieSBjb2xsZWN0aW9uCgpgYGB7ciwgcmVzdWx0cz0iYXNpcyJ9CnBvZW1zICU+JSAKICBkaXN0aW5jdChjb2xsZWN0aW9uKSAlPiUKICBwdWxsKCkgJT4lCiAgbWFwKH4KICAgIHVucHJvamVjdGVkX2xvY2F0aW9ucyAlPiUKICAgICAgZmlsdGVyKGNvbGxlY3Rpb249PS54KSAlPiUKICAgICAgYXJyYW5nZShkZXNjKG4pKSAlPiUKICAgICAgc2VsZWN0KC1jb2xsZWN0aW9uKSAlPiUKICAgICAgZ3QoKSAlPiUKICAgICAgdGFiX2hlYWRlcihzdHJfYygiUG9lbSBsb2NhdGlvbnMgbm90IG1hcHBlZCBpbiAiLC54KSkgJT4lCiAgICAgIGZtdF9pbnRlZ2VyKG4pCiAgKQpgYGAKCiMgSW5mb3JtYW50cwoKYGBge3J9CnJhd19tZXRhICU+JSAKICBmaWx0ZXIoZmllbGQ9PSJJTkYiKSAlPiUKICBtdXRhdGUodmFsdWVfYz1zdHJfcmVwbGFjZV9hbGwodmFsdWUsIl5cXHMqW0EtWmEtesOFw4TDlsOlw6TDtl1bYS16w6XDpMO2XVthLXrDpcOkw7ZdK1xcLiIsIiIpKSAlPiUgCiAgbXV0YXRlKG5hbWU9c3RyX3JlcGxhY2VfYWxsKHZhbHVlX2MsIlxccypcIiooW0EtWmEtesOFw4TDlsOlw6TDtl0/W2EtesOlw6TDtl0/W2EtesOlw6TDtl0/XFwuP1teOy4sXSspKC58XFxuKSoiLCJcXDEiKSkgJT4lIAogIGdyb3VwX2J5KG5hbWUpICU+JSAKICBzdW1tYXJpc2Uob3JpZ3M9c3RyX2ZsYXR0ZW4oc3FsKCJkaXN0aW5jdCB2YWx1ZSIpLGNvbGxhcHNlPSJ8Iiksbj1uKCksLmdyb3Vwcz0iZHJvcCIpICU+JSAKICBjb2xsZWN0KCkKYGBgCgoKIyBQb2VtIHR5cGVzCgpgYGB7cn0KcG9lbXMgJT4lIAogIGZpbHRlcihjb2xsZWN0aW9uIT0ibGl0ZXJhcnkiKSAlPiUKICBsZWZ0X2pvaW4ocG9lbV90aGVtZSAlPiUgZmlsdGVyKGlzX21pbm9yPT0wKSAlPiUgaW5uZXJfam9pbih0aGVtZXMgJT4lIG11dGF0ZSh0aGVtZV90eXBlPWlmX2Vsc2Uoc3RyX2RldGVjdCh0aGVtZV9pZCwiXmVyYWJfb3JpZyIpLCJOb24tdW5pZmllZCIsIlVuaWZpZWQiKSkpKSAlPiUgCiAgZ3JvdXBfYnkoY29sbGVjdGlvbixwX2lkKSAlPiUKICBzdW1tYXJpc2UodGhlbWVfdHlwZT1jYXNlX3doZW4oCiAgICBhbnkodGhlbWVfdHlwZT09IlVuaWZpZWQiKSB+ICJTeXN0ZW1hdGlzb2l0dWphIiwgCiAgICBhbnkodGhlbWVfdHlwZT09Ik5vbi11bmlmaWVkIikgfiAiVmFpbiBlaS1zeXN0ZW1hdGlzb2l0dWphIiwgCiAgICBUIH4gIkVpIGFubm90b2ludGVqYSIpLCAuZ3JvdXBzPSJkcm9wIikgJT4lCiAgY291bnQoY29sbGVjdGlvbix0aGVtZV90eXBlKSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgbXV0YXRlKGNvbGxlY3Rpb249ZmN0X3JldihmY3RfcmVsZXZlbChzdHJfdG9fdXBwZXIoY29sbGVjdGlvbiksIkVSQUIiLCJTS1ZSIiwiSlIiKSksdGhlbWVfdHlwZT1mY3RfcmV2KGZjdF9yZWxldmVsKHRoZW1lX3R5cGUsIlN5c3RlbWF0aXNvaXR1amEiLCJWYWluIGVpLXN5c3RlbWF0aXNvaXR1amEiLCJFaSBhbm5vdG9pbnRlamEiKSkpICU+JQogIGdncGxvdChhZXMoeD1jb2xsZWN0aW9uLHk9bixmaWxsPXRoZW1lX3R5cGUpKSArIAogIGdlb21fY29sKCkgKyAKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKCkgKyAKICB4bGFiKCJLb2tvZWxtYSIpICsKICB5bGFiKCJSdW5vamEiKSArCiAgbGFicyhmaWxsPSJSdW5vdHl5cHBpYW5ub3RhYXRpb3QiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJib3R0b20iKSArCiAgZ3VpZGVzKGZpbGwgPSBndWlkZV9sZWdlbmQocmV2ZXJzZSA9IFRSVUUpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6Om51bWJlcikgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCgojIFNwYXRpb3RlbXBvcmFsIG92ZXJ2aWV3CgpgYGB7cn0KZCA8LSBwb2VtcyAlPiUKICBsZWZ0X2pvaW4ocF95ZWFyICU+JSBtdXRhdGUoeWVhcj1pZl9lbHNlKHllYXIgJWluJSBjKDBMLDk5OTlMKSxOQSx5ZWFyKSkpICU+JSAKICBjb2xsZWN0KCkgJT4lCiAgbXV0YXRlKHllYXJfbnRpbGU9bnRpbGUoeWVhciwxMSkpICU+JQogIGdyb3VwX2J5KHllYXJfbnRpbGUpICU+JQogIG11dGF0ZSh5ZWFycz1zdHJfYyhtaW4oeWVhciksIi0iLG1heCh5ZWFyKSkpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBsZWZ0X2pvaW4ocF9sb2MgJT4lIGNvbGxlY3QoKSkgJT4lIAogIGNvdW50KHllYXJzLGxvY19pZCkgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBsZWZ0X2pvaW4obG9jYXRpb25zICU+JSBzZWxlY3QobG9jX2lkLG5hbWUpICU+JSBjb2xsZWN0KCkpCmBgYAoKCmBgYHtyLGZpZy5oZWlnaHQ9MTEsIHJlc3VsdHM9ImFzaXMifQpwb2x5Z29ucyAlPiUgCiAgbGVmdF9qb2luKGQgJT4lIGNvbXBsZXRlKG5hbWUseWVhcnMpKSAlPiUKICB0bV9zaGFwZSgpICsKICB0bV9wb2x5Z29ucyhjb2w9J24nLCBpZD0nbmFtZScsIHN0eWxlPSdmaXNoZXInLCBwYWxldHRlPSdwbGFzbWEnKSArCiAgdG1fbGF5b3V0KG1haW4udGl0bGU9Ikdlb2dyYXBoaWNhbCBvdmVydmlld3MgYnkgdGltZSIsbGVnZW5kLm91dHNpZGUuc2l6ZT0wLjEpICsKICB0bV9mYWNldHMoYnk9InllYXJzIixuY29sPTQpCmBgYAoKIyBQb2VtIGxlbmd0aCBzdGF0aXN0aWNzCgojIyBCeSBjb2xsZWN0aW9uCgpgYGB7cn0KcG9lbV9zdGF0cyAlPiUKICBmaWx0ZXIobnZlcnNlczw9NzUpICU+JQogIGlubmVyX2pvaW4ocG9lbXMpICU+JQogIGNvdW50KGNvbGxlY3Rpb24sbnZlcnNlcykgJT4lCiAgdW5ncm91cCgpICU+JQogIGdncGxvdChhZXMoeD1udmVyc2VzLHk9bikpICsKICBnZW9tX2NvbCh3aWR0aD0xKSArCiAgZmFjZXRfd3JhcCh+Y29sbGVjdGlvbixzY2FsZXM9ImZyZWVfeSIpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6Y29tbWFfZm9ybWF0KCkpICsKICB4bGFiKCJOdW1iZXIgb2YgdmVyc2UgbGluZXMiKSArCiAgeWxhYigiUG9lbXMiKSArCiAgbGFicyh0aXRsZT0iTnVtYmVyIG9mIHZlcnNlIGxpbmVzIikKYGBgCgpgYGB7cn0KcG9lbV9zdGF0cyAlPiUKICBpbm5lcl9qb2luKHBvZW1zKSAlPiUKICBjb3VudChjb2xsZWN0aW9uLG52ZXJzZXMpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBncm91cF9ieShjb2xsZWN0aW9uKSAlPiUKICBtdXRhdGUocHJvcD1uL3N1bShuKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcihudmVyc2VzPD03NSkgJT4lCiAgZ2dwbG90KGFlcyh4PW52ZXJzZXMseT1jb2xsZWN0aW9uLGZpbGw9Y29sbGVjdGlvbixoZWlnaHQ9cHJvcCkpICsKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKHN0YXQ9J2lkZW50aXR5JykgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwojICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogIHhsYWIoIk51bWJlciBvZiB2ZXJzZSBsaW5lcyIpICsKICB5bGFiKCJQb2VtcyIpICsKICBsYWJzKHRpdGxlPSJOdW1iZXIgb2YgdmVyc2UgbGluZXMiKQpgYGAKCiMjIyBQb2VtcyB3aXRoIG1vcmUgdGhhbiA3NSB2ZXJzZSBsaW5lcwoKYGBge3J9CnBvZW1fc3RhdHMgJT4lCiAgaW5uZXJfam9pbihwb2VtcykgJT4lCiAgY291bnQoY29sbGVjdGlvbixudmVyc2VzKSAlPiUKICBtdXRhdGUobmw9aWZfZWxzZShudmVyc2VzPjc1LG4sMEwpKSAlPiUKICBncm91cF9ieShjb2xsZWN0aW9uKSAlPiUKICBzdW1tYXJpc2UobGluZXM9c3VtKG5sKSxwcm9wb3J0aW9uPXN1bShubCkvc3VtKG4pLC5ncm91cHM9ImRyb3AiKSAlPiUKICBhcnJhbmdlKGRlc2MobGluZXMpKSAlPiUKICBndCgpICU+JQogIHRhYl9oZWFkZXIodGl0bGU9IlBvZW1zIHdpdGggbW9yZSB0aGFuIDc1IHZlcnNlIGxpbmVzIikgJT4lCiAgZm10X2ludGVnZXIobGluZXMpICU+JQogIGZtdF9wZXJjZW50KHByb3BvcnRpb24pCmBgYAoKIyMgQnkgY291bnR5CgpgYGB7cixmaWcuaGVpZ2h0PTExfQpwb2VtX3N0YXRzICU+JSAKICBsZWZ0X2pvaW4ocF9sb2MpICU+JSAKICBsZWZ0X2pvaW4obG9jYXRpb25zKSAlPiUgCiAgbGVmdF9qb2luKGxvY2F0aW9ucyxieT1jKCJwYXJfaWQiPSJsb2NfaWQiKSkgJT4lIAogIG11dGF0ZShuYW1lPWlmX2Vsc2UodHlwZS54PT0iY291bnR5IixuYW1lLngsbmFtZS55KSkgJT4lCiAgY291bnQobmFtZSxudmVyc2VzKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZ3JvdXBfYnkobmFtZSkgJT4lCiAgbXV0YXRlKHByb3A9bi9zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIobnZlcnNlczw9NDAsbmFtZSE9IkFodmVuYW5tYWEiKSAlPiUKICBjb2xsZWN0KCkgJT4lCiAgbXV0YXRlKG5hbWU9ZmN0X3Jlb3JkZXIobmFtZSxwcm9wLC5mdW49bWF4KSkgJT4lCiAgZ2dwbG90KGFlcyh4PW52ZXJzZXMseT1uYW1lLGhlaWdodD1wcm9wKSkgKwogIGdlb21fZGVuc2l0eV9yaWRnZXMoc3RhdD0naWRlbnRpdHknKSArCiAgdGhlbWVfaHNjaV9jb250aW51b3VzKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKIyAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICB4bGFiKCJOdW1iZXIgb2YgdmVyc2UgbGluZXMiKSArCiAgeWxhYigiUG9lbXMiKSArCiAgZ3VpZGVzKGZpbGw9Im5vbmUiKSArCiAgbGFicyh0aXRsZT0iTnVtYmVyIG9mIHZlcnNlIGxpbmVzIGJ5IGNvdW50eSIpCmBgYAoKIyBQb2VtIHZlcnNlIHN0YXRpc3RpY3MKCiMjIEJ5IGNvbGxlY3Rpb24KCiMjIyBMaW5lIHR5cGVzCgpgYGB7cn0KZCA8LSB2ZXJzZXMgJT4lIAogIGxlZnRfam9pbih2ZXJzZV9wb2VtKSAlPiUgCiAgbGVmdF9qb2luKHBvZW1zKSAlPiUgCiAgY291bnQoY29sbGVjdGlvbix0eXBlKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UoY29sbGVjdGlvbixkZXNjKG4pKSAlPiUKICBjb2xsZWN0KCkKYGBgCgoKYGBge3J9CmQgJT4lIAogIGdyb3VwX2J5KGNvbGxlY3Rpb24pICU+JQogIG11dGF0ZShwcm9wb3J0aW9uPW4vc3VtKG4pKSAlPiUKICBndCgpICU+JQogIGZtdF9pbnRlZ2VyKG4pICU+JQogIGZtdF9wZXJjZW50KHByb3BvcnRpb24pCmBgYAoKIyMjIFZlcnNlIGxpbmUgbGVuZ3RocwoKYGBge3J9CmRfbnJfY2hhcmFjdGVycyA8LSB2ZXJzZXNfY2wgJT4lCiAgbXV0YXRlKG5yX2NoYXJhY3RlcnM9c3RyX2xlbmd0aCh0ZXh0KSkgJT4lCiAgbGVmdF9qb2luKHZlcnNlX3BvZW0pICU+JSAKICBsZWZ0X2pvaW4ocG9lbXMpICU+JSAKICBjb3VudChjb2xsZWN0aW9uLG5yX2NoYXJhY3RlcnMpICU+JSAKICB1bmdyb3VwKCkgJT4lCiAgYXJyYW5nZShjb2xsZWN0aW9uLGRlc2MobikpICU+JQogIGNvbGxlY3QoKQoKZF9ucl93b3JkcyA8LSB3b3JkX29jYyAlPiUKICBncm91cF9ieSh2X2lkKSAlPiUKICBzdW1tYXJpc2UobnJfd29yZHM9bWF4KHBvcyksLmdyb3Vwcz0iZHJvcCIpICU+JQogIGxlZnRfam9pbih2ZXJzZV9wb2VtKSAlPiUKICBsZWZ0X2pvaW4ocG9lbXMpICU+JSAKICBjb3VudChjb2xsZWN0aW9uLG5yX3dvcmRzKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UoY29sbGVjdGlvbixkZXNjKG4pKSAlPiUKICBjb2xsZWN0KCkKYGBgCgojIyMjIFZlcnNlIGxpbmUgbGVuZ3RocyBpbiBjaGFyYWN0ZXJzCmBgYHtyfQpkX25yX2NoYXJhY3RlcnMgJT4lIAogIGZpbHRlcihucl9jaGFyYWN0ZXJzPD02MCkgJT4lCiAgZ2dwbG90KGFlcyh4PW5yX2NoYXJhY3RlcnMseT1uKSkgKwogIGdlb21fY29sKHdpZHRoPTEpICsKICBmYWNldF93cmFwKH5jb2xsZWN0aW9uLHNjYWxlcz0iZnJlZV95IikgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHM9c2NhbGVzOjpjb21tYV9mb3JtYXQoKSkgKwogIHhsYWIoIk51bWJlciBvZiBjaGFyYWN0ZXJzIikgKwogIHlsYWIoIlZlcnNlcyIpICsKICBsYWJzKHRpdGxlPSJOdW1iZXIgb2YgY2hhcmFjdGVycyBpbiB2ZXJzZSBsaW5lcyIpCmBgYAoKYGBge3J9CmRfbnJfY2hhcmFjdGVycyAlPiUgCiAgZ3JvdXBfYnkoY29sbGVjdGlvbikgJT4lCiAgbXV0YXRlKHByb3A9bi9zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIobnJfY2hhcmFjdGVyczw9NjApICU+JQogIGdncGxvdChhZXMoeD1ucl9jaGFyYWN0ZXJzLHk9Y29sbGVjdGlvbixmaWxsPWNvbGxlY3Rpb24saGVpZ2h0PXByb3ApKSArCiAgZ2VvbV9kZW5zaXR5X3JpZGdlcyhzdGF0PSdpZGVudGl0eScpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKIyAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICB4bGFiKCJOdW1iZXIgb2YgY2hhcmFjdGVycyIpICsKICB5bGFiKCJWZXJzZXMiKSArCiAgbGFicyh0aXRsZT0iTnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gdmVyc2UgbGluZXMiKQpgYGAKCiMjIyMgVmVyc2UgbGluZXMgd2l0aCBtb3JlIHRoYW4gNjAgY2hhcmFjdGVycwoKYGBge3J9CmRfbnJfY2hhcmFjdGVycyAlPiUgCiAgbXV0YXRlKG5sPWlmX2Vsc2UobnJfY2hhcmFjdGVycz42MCxuLDBMKSkgJT4lCiAgZ3JvdXBfYnkoY29sbGVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKGxpbmVzPXN1bShubCkscHJvcG9ydGlvbj1zdW0obmwpL3N1bShuKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgYXJyYW5nZShkZXNjKGxpbmVzKSkgJT4lCiAgZ3QoKSAlPiUKICB0YWJfaGVhZGVyKHRpdGxlPSJWZXJzZSBsaW5lcyB3aXRoIG1vcmUgdGhhbiA2MCBjaGFyYWN0ZXJzIikgJT4lCiAgZm10X2ludGVnZXIobGluZXMpICU+JQogIGZtdF9wZXJjZW50KHByb3BvcnRpb24pCmBgYAoKCiMjIyMgVmVyc2UgbGluZSBsZW5ndGhzIGluIHdvcmRzCmBgYHtyfQpkX25yX3dvcmRzICU+JSAKICBmaWx0ZXIobnJfd29yZHM8PTEwKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bnJfd29yZHMseT1uKSkgKwogIGdlb21fY29sKHdpZHRoPTEpICsKICBmYWNldF93cmFwKH5jb2xsZWN0aW9uLHNjYWxlcz0iZnJlZV95IikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsMTAsYnk9MikpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6Y29tbWFfZm9ybWF0KCkpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICB4bGFiKCJOdW1iZXIgb2Ygd29yZHMiKSArCiAgeWxhYigiVmVyc2VzIikgKwogIGxhYnModGl0bGU9Ik51bWJlciBvZiB3b3JkcyBpbiB2ZXJzZSBsaW5lcyIpCmBgYAoKYGBge3J9CmRfbnJfd29yZHMgJT4lIAogIGZpbHRlcihucl93b3Jkczw9MTApICU+JQogIHVuY291bnQobikgJT4lCiAgZ2dwbG90KGFlcyh4PW5yX3dvcmRzLHk9Y29sbGVjdGlvbixmaWxsPWNvbGxlY3Rpb24pKSArCiAgc3RhdF9iaW5saW5lKGJpbndpZHRoPTEpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzPXNlcSgwLDEwLGJ5PTIpKSArCiAgeGxhYigiTnVtYmVyIG9mIHdvcmRzIikgKwogIHlsYWIoIlZlcnNlcyIpICsKIyAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscz1zY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCkpICsKICBsYWJzKHRpdGxlPSJOdW1iZXIgb2Ygd29yZHMgaW4gdmVyc2UgbGluZXMiKQpgYGAKCiMjIyMgVmVyc2UgbGluZXMgd2l0aCBtb3JlIHRoYW4gMTAgd29yZHMKCmBgYHtyfQpkX25yX3dvcmRzICU+JSAKICBtdXRhdGUobmw9aWZfZWxzZShucl93b3Jkcz4xMCxuLDBMKSkgJT4lCiAgZ3JvdXBfYnkoY29sbGVjdGlvbikgJT4lCiAgc3VtbWFyaXNlKGxpbmVzPXN1bShubCkscHJvcG9ydGlvbj1zdW0obmwpL3N1bShuKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgYXJyYW5nZShkZXNjKGxpbmVzKSkgJT4lCiAgZ3QoKSAlPiUKICB0YWJfaGVhZGVyKHRpdGxlPSJWZXJzZSBsaW5lcyB3aXRoIG1vcmUgdGhhbiAxMCB3b3JkcyIpICU+JQogIGZtdF9pbnRlZ2VyKGxpbmVzKSAlPiUKICBmbXRfcGVyY2VudChwcm9wb3J0aW9uKQpgYGAKCmBgYHtyfQp2ZXJzZV9ucl93b3JkcyA8LSB3b3JkX29jYyAlPiUgCiAgZ3JvdXBfYnkodl9pZCkgJT4lCiAgc3VtbWFyaXNlKG5yX3dvcmRzPW1heChwb3MpKSAlPiUKICBjb21wdXRlX2EodW5pcXVlX2luZGV4ZXM9bGlzdChjKCJ2X2lkIiwibnJfd29yZHMiKSkpCgp3b3JkX25yX2NoYXJhY3RlcnMgPC0gd29yZHMgJT4lCiAgbXV0YXRlKG5yX2NoYXJhY3RlcnM9c3RyX2xlbmd0aCh0ZXh0KSkgJT4lCiAgc2VsZWN0KHdfaWQsbnJfY2hhcmFjdGVycykgJT4lCiAgY29tcHV0ZV9hKHVuaXF1ZV9pbmRleGVzPWxpc3QoYygid19pZCIsIm5yX2NoYXJhY3RlcnMiKSkpCgpkIDwtIHdvcmRfb2NjICU+JQogIGxlZnRfam9pbih3b3JkX25yX2NoYXJhY3RlcnMpICU+JQogIGxlZnRfam9pbih2ZXJzZV9ucl93b3JkcykgJT4lCiAgbGVmdF9qb2luKHZlcnNlX3BvZW0gJT4lIHNlbGVjdCgtcG9zKSxieT1jKCJ2X2lkIikpICU+JSAKICBsZWZ0X2pvaW4ocG9lbXMpICU+JSAKICBjb3VudChjb2xsZWN0aW9uLG5yX3dvcmRzLHBvcyxucl9jaGFyYWN0ZXJzKSAlPiUKICBjb2xsZWN0KCkKYGBgCgojIyBCeSBjb3VudHkKCiMjIyBWZXJzZSBsaW5lIGxlbmd0aHMKCmBgYHtyfQpkX25yX2NoYXJhY3RlcnMgPC0gdmVyc2VzX2NsICU+JQogIG11dGF0ZShucl9jaGFyYWN0ZXJzPXN0cl9sZW5ndGgodGV4dCkpICU+JQogIGxlZnRfam9pbih2ZXJzZV9wb2VtKSAlPiUgCiAgbGVmdF9qb2luKHBfbG9jKSAlPiUgCiAgbGVmdF9qb2luKGxvY2F0aW9ucykgJT4lIAogIGxlZnRfam9pbihsb2NhdGlvbnMsYnk9YygicGFyX2lkIj0ibG9jX2lkIikpICU+JSAKICBtdXRhdGUobmFtZT1pZl9lbHNlKHR5cGUueD09ImNvdW50eSIsbmFtZS54LG5hbWUueSkpICU+JQogIGNvdW50KG5hbWUsbnJfY2hhcmFjdGVycykgJT4lIAogIHVuZ3JvdXAoKSAlPiUKICBhcnJhbmdlKG5hbWUsZGVzYyhuKSkgJT4lCiAgY29sbGVjdCgpCgpkX25yX3dvcmRzIDwtIHdvcmRfb2NjICU+JQogIGdyb3VwX2J5KHZfaWQpICU+JQogIHN1bW1hcmlzZShucl93b3Jkcz1tYXgocG9zKSwuZ3JvdXBzPSJkcm9wIikgJT4lCiAgbGVmdF9qb2luKHZlcnNlX3BvZW0pICU+JQogIGxlZnRfam9pbihwX2xvYykgJT4lIAogIGxlZnRfam9pbihsb2NhdGlvbnMpICU+JSAKICBsZWZ0X2pvaW4obG9jYXRpb25zLGJ5PWMoInBhcl9pZCI9ImxvY19pZCIpKSAlPiUgCiAgbXV0YXRlKG5hbWU9aWZfZWxzZSh0eXBlLng9PSJjb3VudHkiLG5hbWUueCxuYW1lLnkpKSAlPiUKICBjb3VudChuYW1lLG5yX3dvcmRzKSAlPiUgCiAgdW5ncm91cCgpICU+JQogIGFycmFuZ2UobmFtZSxkZXNjKG4pKSAlPiUKICBjb2xsZWN0KCkKYGBgCgojIyMjIFZlcnNlIGxpbmUgbGVuZ3RocyBpbiBjaGFyYWN0ZXJzCgpgYGB7cn0KZF9ucl9jaGFyYWN0ZXJzICU+JSAKICBncm91cF9ieShuYW1lKSAlPiUKICBtdXRhdGUocHJvcD1uL3N1bShuKSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGZpbHRlcihucl9jaGFyYWN0ZXJzPD00MCxuYW1lIT0iQWh2ZW5hbm1hYSIpICU+JQogIG11dGF0ZShuYW1lPWZjdF9yZW9yZGVyKG5hbWUscHJvcCwuZnVuPW1heCkpICU+JQogIGdncGxvdChhZXMoeD1ucl9jaGFyYWN0ZXJzLHk9bmFtZSxoZWlnaHQ9cHJvcCkpICsKICBnZW9tX2RlbnNpdHlfcmlkZ2VzKHN0YXQ9J2lkZW50aXR5JykgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwojICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogIHhsYWIoIk51bWJlciBvZiBjaGFyYWN0ZXJzIikgKwogIHlsYWIoIlZlcnNlcyIpICsKICBsYWJzKHRpdGxlPSJOdW1iZXIgb2YgY2hhcmFjdGVycyBpbiB2ZXJzZSBsaW5lcyIpCmBgYAoKIyMjIyBWZXJzZSBsaW5lIGxlbmd0aHMgaW4gd29yZHMKCmBgYHtyLGZpZy5oZWlnaHQ9MTF9CmRfbnJfd29yZHMgJT4lIAogIGZpbHRlcihucl93b3Jkczw4LG5hbWUhPSJBaHZlbmFubWFhIikgJT4lCiAgbXV0YXRlKG5hbWU9ZmN0X3Jlb3JkZXIobmFtZSxuLC5mdW49bWF4KSkgJT4lCiAgdW5jb3VudChuKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bnJfd29yZHMseT1uYW1lKSkgKwogIHN0YXRfYmlubGluZShiaW53aWR0aD0xLHNjYWxlPTAuOSkgKwogIHRoZW1lX2hzY2lfZGlzY3JldGUoYmFzZV9mYW1pbHk9IkFyaWFsIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9c2VxKDAsMTAsYnk9MikpICsKICB4bGFiKCJOdW1iZXIgb2Ygd29yZHMiKSArCiAgeWxhYigiVmVyc2VzIikgKwojICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSkgKwogIGxhYnModGl0bGU9Ik51bWJlciBvZiB3b3JkcyBpbiB2ZXJzZSBsaW5lcyIpCmBgYAoKIyMgTnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gd29yZHMgYnkgdGhlaXIgcG9zaXRpb24KCmBgYHtyfQp2ZXJzZV9ucl93b3JkcyA8LSB3b3JkX29jYyAlPiUgCiAgZ3JvdXBfYnkodl9pZCkgJT4lCiAgc3VtbWFyaXNlKG5yX3dvcmRzPW1heChwb3MpKSAlPiUKICBjb21wdXRlX2EodW5pcXVlX2luZGV4ZXM9bGlzdChjKCJ2X2lkIiwibnJfd29yZHMiKSkpCgp3b3JkX25yX2NoYXJhY3RlcnMgPC0gd29yZHMgJT4lCiAgbXV0YXRlKG5yX2NoYXJhY3RlcnM9c3RyX2xlbmd0aCh0ZXh0KSkgJT4lCiAgc2VsZWN0KHdfaWQsbnJfY2hhcmFjdGVycykgJT4lCiAgY29tcHV0ZV9hKHVuaXF1ZV9pbmRleGVzPWxpc3QoYygid19pZCIsIm5yX2NoYXJhY3RlcnMiKSkpCgpkIDwtIHdvcmRfb2NjICU+JQogIGxlZnRfam9pbih3b3JkX25yX2NoYXJhY3RlcnMpICU+JQogIGxlZnRfam9pbih2ZXJzZV9ucl93b3JkcykgJT4lCiAgbGVmdF9qb2luKHZlcnNlX3BvZW0gJT4lIHNlbGVjdCgtcG9zKSxieT1jKCJ2X2lkIikpICU+JSAKICBsZWZ0X2pvaW4ocG9lbXMpICU+JSAKICBjb3VudChjb2xsZWN0aW9uLG5yX3dvcmRzLHBvcyxucl9jaGFyYWN0ZXJzKSAlPiUKICBjb2xsZWN0KCkKYGBgCgpgYGB7cn0KZCAlPiUKICBncm91cF9ieShjb2xsZWN0aW9uLG5yX3dvcmRzLHBvcykgJT4lCiAgbXV0YXRlKHByb3A9bi9zdW0obikpICU+JQogIHVuZ3JvdXAoKSAlPiUKICBmaWx0ZXIobnJfd29yZHM+PTJMLG5yX3dvcmRzPD01TCkgJT4lCiAgbXV0YXRlKG5yX3dvcmRzPWFzX2ZhY3Rvcihucl93b3JkcykscG9zPWFzX2ZhY3Rvcihwb3MpKSAlPiUKICB1bmNvdW50KG4pICU+JQogIGdncGxvdChhZXMoeD1ucl9jaGFyYWN0ZXJzLHk9bnJfd29yZHMsZmlsbD1wb3MpKSArCiAgc3RhdF9iaW5saW5lKGJpbndpZHRoPTEpICsKICBmYWNldF9ncmlkKGNvbGxlY3Rpb25+cG9zLGxhYmVsbGVyID0gbGFiZWxsZXIocG9zPWxhYmVsX2JvdGgpKSArIAogIHhsYWIoIk51bWJlciBvZiBjaGFyYWN0ZXJzIGluIHdvcmQiKSArCiAgeWxhYigiTnVtYmVyIG9mIHdvcmRzIGluIHZlcnNlIikgKwogIGxhYnMoCiAgICB0aXRsZT0iTnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gd29yZHMgYnkgdGhlaXIgcG9zaXRpb24iLAogICAgc3VidGl0bGU9IkFjY29yZGluZyB0byBsZW5ndGggb2YgdmVyc2UgYW5kIGNvbGxlY3Rpb24iCiAgICApICsKICBndWlkZXMoZmlsbD0ibm9uZSIpICsKICB0aGVtZV9oc2NpX2Rpc2NyZXRlKGJhc2VfZmFtaWx5PSJBcmlhbCIpCmBgYAoKYGBge3J9CmQgJT4lCiAgZ3JvdXBfYnkoY29sbGVjdGlvbixucl93b3Jkcyxwb3MpICU+JQogIG11dGF0ZShwcm9wPW4vc3VtKG4pKSAlPiUKICB1bmdyb3VwKCkgJT4lCiAgZmlsdGVyKG5yX3dvcmRzPj0yTCxucl93b3Jkczw9NUwpICU+JQogIG11dGF0ZShucl93b3Jkcz1hc19mYWN0b3IobnJfd29yZHMpLHBvcz1hc19mYWN0b3IocG9zKSkgJT4lCiAgdW5jb3VudChuKSAlPiUKICBnZ3Bsb3QoYWVzKHg9bnJfY2hhcmFjdGVycyx5PXBvcyxmaWxsPW5yX3dvcmRzKSkgKwogIHN0YXRfYmlubGluZShiaW53aWR0aD0xKSArCiAgZmFjZXRfZ3JpZChjb2xsZWN0aW9ufm5yX3dvcmRzLGxhYmVsbGVyID0gbGFiZWxsZXIobnJfd29yZHM9bGFiZWxfYm90aCkpICsgCiAgeGxhYigiTnVtYmVyIG9mIGNoYXJhY3RlcnMgaW4gd29yZCIpICsKICB5bGFiKCJQb3NpdGlvbiIpICsKICBsYWJzKAogICAgdGl0bGU9Ik51bWJlciBvZiBjaGFyYWN0ZXJzIGluIHdvcmRzIGJ5IHRoZWlyIHBvc2l0aW9uIiwKICAgIHN1YnRpdGxlPSJBY2NvcmRpbmcgdG8gbGVuZ3RoIG9mIHZlcnNlIGFuZCBjb2xsZWN0aW9uIgogICAgKSArCiAgZ3VpZGVzKGZpbGw9Im5vbmUiKSArCiAgdGhlbWVfaHNjaV9kaXNjcmV0ZShiYXNlX2ZhbWlseT0iQXJpYWwiKQpgYGAK